I have two widgets residing one next to each other, WidgetA
and WidgetB
, on a QDialog
, with a horizontal Layout Manager.
I am trying to enforce the following size/resize policies:
For WidgetA
:
- Horizontally: Width should be 900 with the ability to shrink (up to 100), and to expand (to whatever).
- Vertically: Height should be 600 with the ability to expand (to whatever).
For WidgetB
:
- Horizontally: Width should be Fixed to 600.
- Vertically: Height should be 600, with the ability to expand (to whatever) - same as
WidgetA
.
But no matter which size policy I choose for WidgetA, it still won't take up width of 900.
Here's a code sample:
class WidgetA(QTextEdit):
def __init__(self, parent = None):
super(WidgetA, self).__init__(parent)
#self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding) --> WidgetA width still smaller than 900
#self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.MinimumExpanding) --> WidgetA will be set to minimumSizeHint()
#self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) --> not good for me, since I want WidgetA to be able to shrink up to minimumSizeHint().width()
#self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) --> not good for me for the same reason - I want WidgetA to be able to shrink up to minimumSizeHint().width()
def minimumSizeHint(self):
return QSize(100, 600)
def sizeHint(self):
return QSize(900, 600)
class WidgetB(QTextEdit):
def __init__(self, parent = None):
super(WidgetB, self).__init__(parent)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding)
def sizeHint(self):
return QSize(600, 600)
class MainForm(QDialog):
def __init__(self, parent = None):
super(MainForm, self).__init__(parent)
label_a = QLabel('A')
widget_a = WidgetA()
label_a.setBuddy(widget_a)
label_b = QLabel('B')
widget_b = WidgetB()
label_b.setBuddy(widget_b)
hbox = QHBoxLayout()
vbox = QVBoxLayout()
vbox.addWidget(label_a)
vbox.addWidget(widget_a)
widget = QWidget()
widget.setLayout(vbox)
hbox.addWidget(widget)
vbox = QVBoxLayout()
vbox.addWidget(label_b)
vbox.addWidget(widget_b)
widget = QWidget()
widget.setLayout(vbox)
hbox.addWidget(widget)
self.setLayout(hbox)
def run_app():
app = QApplication(sys.argv)
form = MainForm()
form.show()
app.exec_()
if __name__ == '__main__':
run_app()
The closest I could get is when I set:
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding)
On WidgetA
.
It seems like WidgetB
is taking a bite off of WidgetA
's 900 width (eliminating WidgetB
does the trick), but I shouldn't be limited by the window's width.
What's preventing from the window itself (the MainForm
) to automatically expand horizontally in order to account for both WidgetA
's 900 width and WidgetB
's fixed 600 width?
According to the article on Layout Management, the rules applied when adding widgets are as follows:
So the most you can do is to define
sizeHint
andminimumSizeHint
, set a stretch factor greater than all the others, and set a size-policy ofExpanding
. But even with all these things in place, it seems the layout manager is still not guaranteed to honour the size-hint when the minimum-size-hint is less.The problem is that the definition of
Expanding
is not quite strong enough:For whatever reason, the layout manager seems to prioritise shrinking over expanding if another widget has a stronger size-policy (e.g.
Fixed
). This looks like the wrong choice from the point of view of your example, but I suppose there may be other situations where it makes more sense. The behaviour seems to be exactly the same in both Qt4 and Qt5, so I don't know whether it should be considered a bug, or just a quirk of the implementation.The simplest work-around I could come up with to fix your example is to enforce the size-hint of
widget_a
like this:(NB: only tested on Linux with the Openbox window manager).
PS: see also this quite similar SO question: Resize window to fit content.