Layout best practices
-
Hi experts,
before posting I checked for this topic in the forum and I didn't find something similar, so I'm creating this.While I was designing some dialogs I realized that I don't have a "general" workflow to follow to make layouts.
Let me give you an example to better explain you what I mean.Let's say that I have to build the following dialog:
That could be done as:
- Create all the widgets.
- Create one QHBoxLayout (HLayout_0) to contain the QPushButton and the QLineEdit.
- Create one QVBoxLayout to contain both the above layout (HLayout_0) and the QListView below.
- Repeat this twice respectively for the left (Host - VLayoutHost) and the right (Target - VLayoutTarget) side.
- Add the QVBoxLayout to a QGroupBox to have a nice container.
- Repeat this twice for both sides.
- Finally merge the QGroupBox into another QHBoxLayout which will be then set as layout (for the dialog).
What triggered me to start to think about this thread was the creation of the QHBoxLayout just to arrange the push button and the textbox.
I thought that probably I could have achieved the same result (for the entire dialog) just using the QGridLayout (although I didn't try...).
I also thought: aren't all these nested layout reducing efficiency adding overhead to the "graphic engine"?
When there is so much flexibility (to design something) it is easy reach your final work, but it is also easy find yourself soon in a "deadlock" which has (fairly) worked until that point, but it is essentially wrong and it won't allow you to scale your design.- Are you agree with this? Or Am I wrong?
- Do I have to make myself these kind of questions when I "design", or should I more focus on the result and just ignoring the "most efficient" approach?
- What should be, or what is your approach, to make a design following best practices (so to have a scalable design)?
- When do you design do you take into account also how verbose your code will be, or do you just focus on other aspects that I'm "ignoring"?
Every suggestion is more than welcome!
Many thanks!
Best regards,
AGA -
Hi @Chris-Kawa,
first of all congratulation for your 2022 recognition 🏆. I agree with the forum about your great answers.
Many thanks to have taken this time even for me 🙏.Ok, I see that we are generally one the same page about the optimizations. I do like idea that less is better (achieving the same results of course).
Until now (if not right just at the start) I never used designer, also because I probably never done complicated things.
For complicated stuff for sure I would not use designer as well.Can you explain me a bit more the your sentence: Prefer the layouts set on the widgets directly. Less clutter and structure. Faster layout code. Avoid "containers", especially the invisible ones.
Looks an interesting point for me.Thanks for your dialog "workflow", it is super useful have a compare!
Since you mentioned I assume that it is something important that you wanted to highlighted me.
Why should I specify/add objectName to my widgets?
I saw that designer always does it, so I do it as well, but I don't know the "real reason". I thought that just give it a right name on the object instance would have been enough, but from your comment to me looks like something "weak". Can you explain me why?One more what is the grid layout on the groupbox?
Thanks also to @JonB for your thoughts!
Many thanks!
AGA@superaga said:
first of all congratulation for your 2022 recognition
Thank you. That's very kind.
Prefer the layouts set on the widgets directly. Less clutter and structure. Faster layout code. Avoid "containers", especially the invisible ones.
There's two ways to use layouts in the designer - drag&drop one from a side toolbox or select a widget and use the "lay out" option on the top toolbar or from context menu. Looks like this:
The structure generated looks like this:
First one looks a bit nicer in the editor and lets you clearly see grid lines, but it adds an extra level (or two!) of elements. If you already have a layout in the parent it will add that new layout as a child using QBoxLayout::addLayout(). If you don't have a layout in the parent it will create an extra dummy widget and set that layout on it, which is one of those hidden "containers" that I mentioned, serving no other purpose than easy editing.Faster code part comes from the fact that there are fewer levels to go through when calculating position and size for widgets. A single layout vs. layout+layout or parent+dummy+layout. It's not a big difference in a form like this one, but when you build larger UIs it adds up quite a lot.
Since you mentioned I assume that it is something important that you wanted to highlighted me.
Just that if you can make something with one layout it's IMO better than two i.e. one grid vs vbox+hbox.
Why should I specify/add objectName to my widgets?
I might have misspoken there. I just meant the variable names really, because I too often see code like
ui->groupBox_17->...
, so I always properly rename my layout elements to reflect what they do.
As for setting object names - it's not needed if you don't plan on using it somehow e.g. for QObject::findChild(). Designer does it so you don't have to, but if you don't use it it's really just another overhead that you might not want in a larger design. It's not a lot, but all those strings take some space, so if you don't use them they're just bloat.One more what is the grid layout on the groupbox?
What I mentioned above - select a groupbox and use the "lay out" option. It's basically like doing this from code:
layout = new QVBoxLayout(widget); layout->addWidget(...); layout->addWidget(...);
where the drag&drop layout would be something like this:
layout = new QVBoxLayout(); layout->addWidget(...); layout->addWidget(...); dummy = new QVBoxLayout(widget); dummy->addLayout(layout);
-
Hi experts,
before posting I checked for this topic in the forum and I didn't find something similar, so I'm creating this.While I was designing some dialogs I realized that I don't have a "general" workflow to follow to make layouts.
Let me give you an example to better explain you what I mean.Let's say that I have to build the following dialog:
That could be done as:
- Create all the widgets.
- Create one QHBoxLayout (HLayout_0) to contain the QPushButton and the QLineEdit.
- Create one QVBoxLayout to contain both the above layout (HLayout_0) and the QListView below.
- Repeat this twice respectively for the left (Host - VLayoutHost) and the right (Target - VLayoutTarget) side.
- Add the QVBoxLayout to a QGroupBox to have a nice container.
- Repeat this twice for both sides.
- Finally merge the QGroupBox into another QHBoxLayout which will be then set as layout (for the dialog).
What triggered me to start to think about this thread was the creation of the QHBoxLayout just to arrange the push button and the textbox.
I thought that probably I could have achieved the same result (for the entire dialog) just using the QGridLayout (although I didn't try...).
I also thought: aren't all these nested layout reducing efficiency adding overhead to the "graphic engine"?
When there is so much flexibility (to design something) it is easy reach your final work, but it is also easy find yourself soon in a "deadlock" which has (fairly) worked until that point, but it is essentially wrong and it won't allow you to scale your design.- Are you agree with this? Or Am I wrong?
- Do I have to make myself these kind of questions when I "design", or should I more focus on the result and just ignoring the "most efficient" approach?
- What should be, or what is your approach, to make a design following best practices (so to have a scalable design)?
- When do you design do you take into account also how verbose your code will be, or do you just focus on other aspects that I'm "ignoring"?
Every suggestion is more than welcome!
Many thanks!
Best regards,
AGA@superaga
I think you are over-thinking/worrying. A fewQ[HV]BoxLayout
s is fine and intended. Probably don't use aQGridLayout
unless you really have grid-type stuff. It's possible you might need it to get the Host & Target boxes to be exactly the same size, but (within reason) if you can do it all withQ[HV]BoxLayout
s that's good. -
@superaga Treat my answers as opinion, not universal truths, but here's my take on it.
Are you agree with this? Or Am I wrong?
I think the level of flexibility Qt provides is pretty good when it comes to UIs. It's true that the more options you have the easier it gets to overcomplicate your design and slow the whole thing down. That's where experience comes in. Having options is good, but understanding how to use them well is far better. As for deadlocks - unless you really go out of your way to make it super complicated it's quite easy to move stuff around. Even if the designer doesn't let you do a particular refactor easily the .ui file is just an xml in the end. Notepad will let you do whatever you want. I've been doing widget UIs with Qt for 15 years (gosh, I'm old) and I don't think I ever got myself into a situation where changing something is just too difficult to do.
Do I have to make myself these kind of questions when I "design", or should I more focus on the result and just ignoring the "most efficient" approach?
Depends on who you ask. Some will tell you it doesn't matter as long as the effect works like you want and hardware will just pick up the additional workload. I'm a low level programmer and my approach is that you can actually achieve better designs by simplifying and optimizing them. From my experience the fewer elements the ui has (not just the visible ones, but layouts, containers etc.) the better it works, the faster it is and the easier to maintain it is.
What should be, or what is your approach, to make a design following best practices (so to have a scalable design)?
I don't think there's a unified set of best practices. As I said different shops do it differently.
My set of rules, which certainly is not gonna be good for everyone, is:- Avoid designer for simple things. It's less code, generators etc. so faster compile time. It's simpler code too and everything is easily discoverable. Nothing like a young programmer sticking little bits and pieces of stylesheets in random widgets in designer. Good luck finding where that 2px of padding comes from after a year or two.
- Avoid designer for complicated things. It's simply not powerful enough and you end up with hybrid designer/code widgets, which is not fun to maintain.
- For designer work avoid inserting layouts as items. Prefer the layouts set on the widgets directly. Less clutter and structure. Faster layout code. Avoid "containers", especially the invisible ones. If you have to complicate the layout and add runtime overhead for the sake of a bit easier editing there's something wrong.
When do you design do you take into account also how verbose your code will be, or do you just focus on other aspects that I'm "ignoring"?
Some do, some don't. I do. I'm a minimalist and try to declutter every component of the system - designer forms, code, project structure, number of files. You'll sometimes see people saying that a design can either be pretty or fast and that optimization somehow makes the code/ui less readable. I wholeheartedly disagree. It just takes some time and practice to get to the level that both come naturally and are not at odds with each other.
As for the example above here's how I would do it. It's not the only or best way, but gives you something to compare your workflow to:
- Add groupbox, set name and label
- Add button, line edit and textbox to it. Give them names
- Set a grid layout on the groupbox (not instert a grid layout element inside!)
- Adjust button/line edit position, either via max/fixed width of the button or stretch weights, depending on the result you want to achieve.
- Copy/paste entire groupbox, rename copied widgets
- Add a horizontal layout to the parent
Result would be the same, similar amount of work (I'd say a bit less even), no elements that serve only editing, and faster layout code (just one layout in the groupbox instead of nesting).
-
Hi @Chris-Kawa,
first of all congratulation for your 2022 recognition 🏆. I agree with the forum about your great answers.
Many thanks to have taken this time even for me 🙏.Ok, I see that we are generally one the same page about the optimizations. I do like idea that less is better (achieving the same results of course).
Until now (if not right just at the start) I never used designer, also because I probably never done complicated things.
For complicated stuff for sure I would not use designer as well.Can you explain me a bit more the your sentence: Prefer the layouts set on the widgets directly. Less clutter and structure. Faster layout code. Avoid "containers", especially the invisible ones.
Looks an interesting point for me.Thanks for your dialog "workflow", it is super useful have a compare!
Since you mentioned I assume that it is something important that you wanted to highlighted me.
Why should I specify/add objectName to my widgets?
I saw that designer always does it, so I do it as well, but I don't know the "real reason". I thought that just give it a right name on the object instance would have been enough, but from your comment to me looks like something "weak". Can you explain me why?One more what is the grid layout on the groupbox?
Thanks also to @JonB for your thoughts!
Many thanks!
AGA -
Hi @Chris-Kawa,
first of all congratulation for your 2022 recognition 🏆. I agree with the forum about your great answers.
Many thanks to have taken this time even for me 🙏.Ok, I see that we are generally one the same page about the optimizations. I do like idea that less is better (achieving the same results of course).
Until now (if not right just at the start) I never used designer, also because I probably never done complicated things.
For complicated stuff for sure I would not use designer as well.Can you explain me a bit more the your sentence: Prefer the layouts set on the widgets directly. Less clutter and structure. Faster layout code. Avoid "containers", especially the invisible ones.
Looks an interesting point for me.Thanks for your dialog "workflow", it is super useful have a compare!
Since you mentioned I assume that it is something important that you wanted to highlighted me.
Why should I specify/add objectName to my widgets?
I saw that designer always does it, so I do it as well, but I don't know the "real reason". I thought that just give it a right name on the object instance would have been enough, but from your comment to me looks like something "weak". Can you explain me why?One more what is the grid layout on the groupbox?
Thanks also to @JonB for your thoughts!
Many thanks!
AGA@superaga said:
first of all congratulation for your 2022 recognition
Thank you. That's very kind.
Prefer the layouts set on the widgets directly. Less clutter and structure. Faster layout code. Avoid "containers", especially the invisible ones.
There's two ways to use layouts in the designer - drag&drop one from a side toolbox or select a widget and use the "lay out" option on the top toolbar or from context menu. Looks like this:
The structure generated looks like this:
First one looks a bit nicer in the editor and lets you clearly see grid lines, but it adds an extra level (or two!) of elements. If you already have a layout in the parent it will add that new layout as a child using QBoxLayout::addLayout(). If you don't have a layout in the parent it will create an extra dummy widget and set that layout on it, which is one of those hidden "containers" that I mentioned, serving no other purpose than easy editing.Faster code part comes from the fact that there are fewer levels to go through when calculating position and size for widgets. A single layout vs. layout+layout or parent+dummy+layout. It's not a big difference in a form like this one, but when you build larger UIs it adds up quite a lot.
Since you mentioned I assume that it is something important that you wanted to highlighted me.
Just that if you can make something with one layout it's IMO better than two i.e. one grid vs vbox+hbox.
Why should I specify/add objectName to my widgets?
I might have misspoken there. I just meant the variable names really, because I too often see code like
ui->groupBox_17->...
, so I always properly rename my layout elements to reflect what they do.
As for setting object names - it's not needed if you don't plan on using it somehow e.g. for QObject::findChild(). Designer does it so you don't have to, but if you don't use it it's really just another overhead that you might not want in a larger design. It's not a lot, but all those strings take some space, so if you don't use them they're just bloat.One more what is the grid layout on the groupbox?
What I mentioned above - select a groupbox and use the "lay out" option. It's basically like doing this from code:
layout = new QVBoxLayout(widget); layout->addWidget(...); layout->addWidget(...);
where the drag&drop layout would be something like this:
layout = new QVBoxLayout(); layout->addWidget(...); layout->addWidget(...); dummy = new QVBoxLayout(widget); dummy->addLayout(layout);
-
Hi again @Chris-Kawa,
Thanks again for your answers.
I'm not used to use designer to make the "skeleton" of the GUI (I feel more confident, and I find it more simple by code) but after read your answer I think that it might be useful to compare the different generated code.
I completely agree regarding the nested layouts and the widgets names too... When the used names are really meaningful, otherwise...
Thanks also for the objectName explanation, now makes sense and no, I never used it and I have same your thoughts on this (objects name are enough).
I can then consider close this thread.
Many thanks!Best regards,
AGA -
This post is deleted!
-
This post is deleted!
This post is deleted!