Speed up UI refresh
-
Hello, I am using pyqt6 on python3.10;
I have a project that opens a window to edit some settings based on some select menu. My issue is that when I select an option it takes quite some time to load all the content and I wish to reduce a bit that effect if possibleThe project is made of a QWidget with a QVBoxLayout and 2 widgets in it:
- a QComboBox with a list of values
- an empty 'content' QWidget
QComboBox has a currentTextChanged callback that:
- clears all widget in the 'content' QWidget
- adds a new QWidget (in the 'content' QWidget's layout )with like 30 QLineEdit and QLabels (+ some buttons)
Underneath, the adds method is a bit more complicated, the labels and linedits text are created from values off a yaml (recursive function on key/values) file that is loaded before hands everytime combobox change I reload the file from disk.
The lineedit texts and label names are subject to change often so I cant have the widget preloaded and hidden with empty values unfortunately
Do you guys maybe know a way to 'build' this widget a bit faster?
-
Hi and welcome to devnet,
Wouldn't a QTableView or QTableWidget make for a more logical editor ?
-
@SGaist Thank you!
I am not entirely sure how a QTableView or Widget could help me there, even aesthetic wise, these are just spreadsheet like thingies? I am doing more like a FormGroup thing see the picture it might be easier to understand:
The type of widget I use to display these labels/inputs doesnt really matter I think, but I can have like 50 of these "forms" in the widget that I load every time. Also each color combox have like 100 colors pre-defined (maybe I should reduce that a bit)
-
One thing that likely costs a lot is the systematic reload of your yaml file. Why not parse it once and then store its values in a model and then just load/update/store from there ?
-
@SGaist Thanks for you reply. This is what I do, I think, only when the select menu change I charge the whole yaml config in a model, and I use it to generated the multiple form. I measured the load time of the yaml its almost instant. I cant store all of them (yamls), because a user might have change it on the disk while the app is running.
For now I load ALL the "forms" on the combobox changes. What I can do is just load one form title (just the title and the toggle arrow button) and generate/display the form when I action the toggle switch.
First time I build a desktop app, I am not sure what are the correct way of doing demanding window generation :D
Maybe there is a way to load all the forms in parallels using threads or something? -
@bashtian said in Speed up UI refresh:
Maybe there is a way to load all the forms in parallels using threads or something?
Seems to be not really an option to use threads here. Anything UI-related can only be done in the main thread.
If all data has the same layout a QTableView could make sense here. Your table columns would be name, width, height, x, y, header_text_color and header_background_color. The QTableView needs a model which would be your own class derived from QAbstractItemModel. The advantage ov QTableView is that it only instantiates the widgets that are currently visible (in contrast to QTableWidget where you would add all widgets after parsing the yaml -> same problem as before).
If you insist on not using QTableView because you want to keep your layout, you should still copy the approach of QTableView. I guess you already have a QScrollArea for all your entries. You get better performance if you only create the widgets for the entries that are currently visible. (On second thought: maybe get rid of QScrollArea and use just the QScrollBar directly.) The scrollbar will tell you what the first entry is to display. You should be able to compute how many entries can be displayed inside the surrounding widget. Just create the necessary widgets and display those (kind of do your own static layouting).