I have this sample of code:
import sys
from PyQt4.QtGui import (QApplication, QHBoxLayout, QVBoxLayout, QDialog,
QFrame, QPushButton, QComboBox)
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
moreButton = QPushButton('moreButton')
moreButton.setCheckable(True)
resizeButton = QPushButton('Resize')
combo = QComboBox()
combo.addItems(['item1', 'item2'])
layout1 = QHBoxLayout()
layout1.addWidget(moreButton)
layout1.addWidget(resizeButton)
layout2 = QHBoxLayout()
layout2.addWidget(combo)
self.frame = QFrame()
self.frame.setLayout(layout2)
self.frame.hide()
layout3 = QVBoxLayout()
layout3.addLayout(layout1)
layout3.addWidget(self.frame)
moreButton.toggled.connect(self.frame.setVisible)
moreButton.clicked.connect(self.method)
resizeButton.clicked.connect(self.method)
self.setLayout(layout3)
self.resize(630, 50)
def method(self):
if self.frame.isVisible():
self.resize(630, 150)
else:
self.resize(630, 250)
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
I run it and when moreButton clicked the ComboBox appears or disappears. Dialog's size also changes. But if I change the method to:
def method(self):
if self.frame.isVisible():
self.resize(630, 150)
else:
self.resize(630, 50)
(in order to set the initial size when combo is hidden) the resizing does not work. However, if I click resizeButton -which is connected to the same method- the resizing works properly.
I know that there are other ways to achieve such a result (eg. layout.setSizeConstraint(QLayout.SetFixedSize)), but I want to declare size explicitly.
What am I doing wrong?
My guess is that you are trying to resize the QDialog
before it has time to re-adjust its size after you hide stuff. So at the time resize
is called it has a minimumSize
that makes sure the buttons and the combobox visible. When you call it after some time, it now has proper miminumSize
and responds properly.
A quick fix is manually overriding minimumSize
before resizing:
def method(self):
if self.frame.isVisible():
# uncomment below, if you like symmetry :)
# self.setMinimumSize(630, 150)
self.resize(630, 150)
else:
self.setMinimumSize(630, 50)
self.resize(630, 50)
But, if I were to tackle this, I'd just leave managing resizing to the layout and use sizeConstraint
. That's what these layouts for anyways.
This question and the answers were helpful in my situation: Automatic sizing of a QDialog with QLayout/QVBoxLayout containing a QLabel of variable size content/message to the user while also avoiding the double arrow cursor at the border of the overall QDialog container. The sizePolicy of the dialog itself was set to Fixed and yet the arrows would appear even though it cannot be resized (wouldn't budge). And even though the inner layout does automatically/magically resize, using SetFixedSize on the layout (surprise, surprise) made those annoying double arrows of the overall QDialog go away.
QDialog: QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
QLayout: setSizeConstraint(QLayout.SetFixedSize)
QLabel: QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
...and now the dialog sizes itself appropriately to the volume contained in the label yet the dialog itself is not (seemingly) user-resizable, which is good for info and error messages.
Seemed counterintuitive to me so I thought worth adding here for others.
A bit more detail...
self.label = QtGui.QLabel(self)
self.label.sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
self.label.setSizePolicy(self.label.sizePolicy)
self.label.setMinimumSize(QtCore.QSize(450, 40))
self.label.setWordWrap(True)
self.verticalLayout = QtGui.QVBoxLayout(self)
# get rid of overall dialog resize arrows
self.verticalLayout.setSizeConstraint(QtGui.QLayout.SetFixedSize) # no resize arrows
self.verticalLayout.addWidget(self.label)
This problem appears to be caused by the order in which events are processed.
Here's a simple fix:
def method(self):
app.processEvents()
if self.frame.isVisible():
self.resize(630, 150)
else:
self.resize(630, 50)
did you try this ? unless i misunderstand, this is what you wanna do.
def method(self):
if self.frame.isVisible():
self.resize(630, 150)
self.frame.setVisible(False)
else:
self.resize(630, 50)
edit : the final answer is layout3.setSizeConstraint(QLayout.SetNoConstraint)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With