On a form designed with Qt Designer, I have two QGroupBoxes with a bunch of controls in each of them. Both group boxes have nearly the same contents (QLineEdits with associated labels).
What I want to do, however, is to align the controls together, as if they were part of the same grid layout. But since they are in separate containers, they can't share the same layout, and I don't want to give them a fixed width.
Is there a way to do it in Qt Designer? If not, is there a way to do it in code?
Thanks!
There is no way to do this in Designer. As far as I know, Qt does not provide a good way to do this in code either. If you really want this, you will probably have to rely on something a little hacky.
Here's my first idea: Override resizeEvent() in the widget that contains the two group boxes to get the preferred size (via sizeHint() or minimumSizeHint()) of all of the labels and set the fixed width of all the labels to the largest preferred width.
I would encourage you to ask yourself if this really matters (is it worth the development time?) and consider whether you can avoid the problem entirely with a slightly different UI design.
BTW, you might want to take a look at QFormLayout if you haven't already.
Related
When i add splitters, it acts as a layout, but also allows to resize the widgets in runtime. So, for example, i managed to lay out my widgets in this way:
Therefore, i can resize my widgets in runtime. As i noticed, this function is also available in designer mode, but it doesn't work properly. I tried to hover over my splitter and drag it in designer mode, but it only replaces the entire widget.
That is how does my main window look like in QtDesigner. I haven't tried to code yet. The problem is, that even though i used to set a stretch factor, my widegt's look in designer mode and in runtime completely differ. They have another sizes.
So, what are the problems:
Firstly, i can't change my widgets sizes properly, using stretch factors. I don't know, i tried to change size policies, but i did't manage to see an effect. I have somehow changed size of the vertically oriented widgets, but when speak about horizontal orientation - stretch factor and size policy doesn't change anything at all.
Secondly, i can't move my splitter in designer mode. It's position is constant, by default, it's always somewhere in the middle.
Thirdly, i have bugs (i think so) with my widget sizes in designer mode. They differ with widget's sizes in runtime.
Question:
So, how can i change widget's sizes properly? Maybe there's a way of moving a splitter in designer mode - do newer versions of Qt have it? Currently i'm using Qt 5.9.9. Also, why these bugs, and are they bugs at all. Maybe i just should update my Qt to newer versions to get access to newer functionalities?
Comment: I'm not sure if stretch factors work with layout as they do with widgets. I'm using layouts exactly the same way i use widgets. My layout's wrong(maybe) use may have caused this problem. Anyways, i'm entirely new to Qt, and may not know something to understand it completely.
Main Question
What is the "right" way to give your widgets default sizes and make sure they contract, expand, or remain fixed if there is additional or not enough space to accommodate them?
How I Think Qt Works
After reading the Qt documentation it seems like the sizing algorithm goes something like this...the layout begins by asking its children for their ideal size via the QWidget::sizeHint method. If the layout has additional space or not enough space then it'll determine which widgets to resize based on each widget's sizing policy (QWidget::sizePolicy), minimum size (QWidget::minimumSize), and maximum size (QWidget::maximumSize).
Why isn't there a QWidget::setSizeHint method?
If my understanding is close to being accurate then it would seem all you'd have to do is set the sizeHint, sizePolicy, maximumSize, and minimumSize on each widget and everything would just work. So why isn't there a setSizeHint method?!?!??!! Sure, every time you use a widget that provides all of the functionality you need (QTableView, QComboBox, etc) you could extend it and override a single method but that sounds absolutely ridiculous.
One of the sizing issues I'm fighting with.
I've got a QMainWindow with a QDockWidget on the left hand side. The QDockWidget has a QTableView. I'd like to have the QDockWidget/QTableView take up a "reasonable" amount of space on start up and then the user can resize it however small or large they'd like.
Unfortunately, when the application starts up it gives the QDockWidget/QTableView so little space that it requires a horizontal scroll bar. The only way I've found to force it to give it a reasonable amount of width is to set the QDockWidget's minimum width but then it prevents the user from resizing it as small as they might like to.
Why isn't there a QWidget::setSizeHint method?
In my opinion it is much better for a widget to compute its preferred size based on its content (or rules) instead of allowing the coder to set a sizeHint probably hardcoded or at least prone to errors.
I almost never had to set a size on a widget, playing with the QSizePolicy was enough. And when I needed some specific constraints, playing with minimum/maximum sizes was enough. So that Qt layouts were always able to adapt the widget.
If you want to set up yourself some percentages on the sizes etc, you can play with the stretch parameter. You can also add spacers when you need empty spaces.
Extending a QWidget to override the QWidget::sizeHint method does not sound ridiculous to me, as you change the widget behaviour by changing its preferred size and that fits the polymorphism spirit of OOD.
How to properly size Qt widgets? is a vague question and depends on the use cases. Most of the time choosing the good layouts and size-policy lets you achieve very adaptative GUI. Qt Designer can help to do this right, even if the layout management is not always intuitive (you need to place your widgets first and then set them in layouts from the inner to the outer layout).
About your specific issue, it's hard to tell why your QDockWidget gets too small without knowing the details of the layout(s) you have around your two widgets in the window. Maybe it is a specific issue with QDockWidget : see related questions :
QDockWidget starting size
Qt 5.7 QDockWidget default size
Prevent QDockWidget autosizing behaviour
I want to create a flexible layout, where the User can resize Widgets, but still give a good default layout. I'm using the Qt Designer for everything.
As a minimal example I used a simple Windows with a Widget and a plainTextEdit. The later one seems to cause the problems, which is why I choose it. At first I built it without the Splitter which worked just fine. The Stretching factors are 1:1 by the way.
Now I put both widgets in a Splitter (by breaking the main layout, putting both widgets in a Splitter and setting a new layout to the main widget). Resizing still works but the stretching factors behave weird:
The PlainTextEdit seems to take up far to much space. The Stretching Factors are still at 1:1. I found a workaournd, by changing the stretching of the upper widget to a much higher value (in this case 9:1), which looks good again:
So my question is: Why do the stretching factors begin to behave weird when I put the images in a Splitter? And how can I solve this without using arbitrary guessed stretching factors?
QSplitter::setSizes() can be used to set relative sizes. According to the documentation, "any additional/missing space is distributed amongst the widgets according to the relative weight of the sizes".
In this case, it is a bit ugly, since you have to add this in your code rather than editing your layout in QDesigner (normally, you would want to define your layout only at one place), but still it is quick and works:
MyWindow::MyWindow(QWidget* parent):
QWidget(parent)
{
m_Ui.setupUi(this);
m_Ui.splitter->setSizes({2000, 1000, 1000});
However, I had to use big numbers (instead of {2, 1, 1}), maybe because at this point, the window is not completely set up yet (apparently, Qt is not a big fan of RAII...). Also, this kind of notation works probably only with a recent C++ version, otherwise you can also define the QList in some extra lines.
Whenever you resize a datagrid by hand (not via code), the last column seems to retain most of the width. What's worse, whenever you extend it and shrink it to a large degree, the other columns can get smushed. Here's a perfect example:
The ideal solution would distribute width equally or in proportion to the length of the text. In addition, if would avoid covering text when it's not necessary. Now, setting the width to 0.5 in the example above does seem to alleviate the issue, but not prevent it entirely.
What I'd also like to know if there are any well polished, custom datagrids out there that solve this. From trying to find a solution, I suspect the only solutions available are more ad-hoc.
I know two ways to avoid this problem.
1) Use List with special item renderer, which simulates columns (say HBox separated with rules), and header, which repeats the layout of item renderer. It's not very elegant solutions, but the resize is quite predictable. Also you can easily add sorting feature (by adding buttons to header), but I'm not sure if column resize is possible to implement here.
2) Use spark s:DataGrid from SDK 4.x. It hasn't got such resize problems AFAIK.
My problem is that we have developed a product using 480x800 on a 10" LCD display, and we want to "give the idea" to a customer who has a PC.
No modestly-priced laptop has a vertical resolution of 800 these days, probably because of 720p standards, but I digress.
Basically, I want to take a suggestion back to the designer, who used Qt, and suggest something that will work. He has already stated that it is impossible, but I suspect that is laziness talking.
As a .NET developer, I know how easy it is to scale a WinForms application, but I don't want to suggest something where I have no expertise, and while searching StackOverflow and Google for tips with scaling and Qt have yielded no results.
Is there something easy to cause an entire application to scale downwards in Qt?
Thanks for any help you can provide.
If you mean normal scaling where some widgets retain their sizes and some scale, then yes, it's really easy (like what a WinForms developer achieves with anchors if I remember correctly). Just a matter of using layouts and spacers. Grid and form layouts are very flexible but in case a more complicated layout is needed it's easy to add a subcontainer that has a different layout. This layout concept is similar to Java SWING and AWT layouts.
Also, if he used Qt Creator to design the ui, then selecting the container and applying grid layout often yields the desired results (it's on the toolbar).
If you mean proportional scaling of all widgets then it's not simple. One would need to override the resizeEvent and scale all widgets accordingly, plus fonts are tricky to scale well.