'How to equally distribute the width of QSplitter
I have a problem with adjusting width of QSplitter
. I prepared UI in Qt Designer and it looks now like that:
Designer view:
And here is my object inspector:
My question is how to divide the width of QSplitter
equally over the left and right area. I would like to get this effect as initial size and then the customer can do whatever he wants.
Effect which I would like to have is the following:
In other worlds, I am looking for a way to specify the splitter initial division of left and right area as 50%/50% of window width. Is there any option to obtain that?
Thank you for your help and please be forgiving, I have just started to learn Qt.
Solution 1:[1]
Short answer
splitter->setSizes(QList<int>({INT_MAX, INT_MAX}));
Note: The fine tuning section may contain essential information if you want other ratios.
Explanation
QSpacer
? No.
You do not need a QSpacer
in this case. The goal of a spacer is to fill all available space.
QSplitter
provides two methods to specify the size of its children:
1. QSplitter::setStretchFactor
? No.
Although the stretch factor may seem to be what you are looking for to specify the relative size of the child widgets, it has the disadvantage for your case that the factors are relative to the initial size of the child widgets:
stretch is not the effective stretch factor; the effective stretch factor is calculated by taking the initial size of the widget and multiplying it with stretch.
Therefore, setting the stretch factor for both children to the same value (ex. 1
) will not work well:
splitter->setStretchFactor(0, 1);
splitter->setStretchFactor(1, 1);
2. QSplitter::setSizes
? Yes.
A better alternative is to use setSizes
, because only the relative sizes matter:
The overall size of the splitter widget is not affected. Instead, any additional/missing space is distributed amongst the widgets according to the relative weight of the sizes.
So, one could think that setting both sizes to one will distribute the total size equally over both children:
splitter->setSizes(QList<int>({1, 1}));
No, because you should take into account that the minimal size policy will be enforced by replacing too small values with their minimal size:
The size policies of the widgets are preserved. That is, a value smaller than the minimal size hint of the respective widget will be replaced by the value of the hint.
So, you should use a value that is greater than the minimal size of your children, for example the greatest number that can be represented with an int
, i.e. INT_MAX
:
splitter->setSizes(QList<int>({INT_MAX, INT_MAX}));
Fine tuning
As suggested in the comments, INT_MAX
may result in some overflow issues, depending on the calculations Qt does with those values. This may be especially the case if you want a non-equal distribution ratio. Therefore, a more sensible large value may be the desktop width/height.
// Horizontal splitter
int largeWidth = QGuiApplication::primaryScreen ()->virtualSize ().width ();
splitter->setSizes(QList<int>({largeWidth , largeWidth}));
// Vertical splitter
int largeHeight = QGuiApplication::primaryScreen ()->virtualSize ().height ();
splitter->setSizes(QList<int>({largeHeight , largeHeight}));
Further reading
Most of the time, Qt does a good job giving all widgets an appropriate size, but tweaking it can become very hard requiring some trial and error. Therefore I want to provide some extra resources which may be useful when working with layout management in Qt:
Solution 2:[2]
Based on m7913d's
To equally divide a splitter use QSplitter::setSizes
, each size in the list should be equal. Use QWidget::minimumSizeHint()
to determine the size to use. Use the maximum width (for horizontal splitters) or the maximum height (for vertical splitters) of every widget you added to the splitter
// Example for a horizontal splitter
splitter = new QSplitter(Qt::Horizontal, this);
splitter->addWidget(widgetLeft);
splitter->addWidget(widgetRight);
auto equalWidth = std::max(widgetLeft->minimumSizeHint().width(),
widgetRight->minimumSizeHint().width());
splitter->setSizes({ equalWidth, equalWidth });
// Example for a vertical splitter
splitter = new QSplitter(Qt::Vertical, this);
splitter->addWidget(widgetTop);
splitter->addWidget(widgetBottom);
auto equalHeight = std::max(widgetTop->minimumSizeHint().height(),
widgetBottom->minimumSizeHint().height());
splitter->setSizes({ equalHeight, equalHeight });
Solution 3:[3]
I would suggest a further variation. The points of m7913d all hold and are important. But in my case (Qt5.13.2) I found that setting large enough sizes could still lead to some variations. I do not know why exactly but setting all the stretch factors to one additionally finally behaved like I wanted.
Also note that setting all stretch factors to one but using non-equal (but still large enough to avoid minimum size constraints) sizes with setSizes
works, too! For example:
splitter->setStretchFactor(0,1);
splitter->setStretchFactor(1,1);
splitter->setSizes({static_cast<int>(10000 / 1.618), static_cast<int>(10000 - 10000 / 1.618)});
sets a golden ratio split.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Seamus Boyle |
Solution 3 | IceFire |