Reputation: 45
I'm trying to resize my app to a smaller size after a widget is hidden and its sizePolicy is set to Ignored. However, the app will not resize to smaller than it was before, as if the hidden widget is still there taking up space.
I've tried including self.update()
, self.updateGeometry()
, and app.processEvents()
after hiding the second widget/setting its sizePolicy to Ignored and before trying to resize the app, but none of them seem to have any effect.
class App(QWidget):
def __init__(self):
super().__init__()
# basic setup
self.move(100, 100)
# main widgets
self.advanced_metadata = QCheckBox("Advanced", self)
self.advanced_metadata.stateChanged.connect(self.displayAdvanced)
self.first_widget = QLabel('first_widget', self)
self.second_widget = QLabel('second_widget', self)
self.second_widget.setHidden(True)
self.second_widget.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
# main layout
self.setLayout(QVBoxLayout())
self.layout().addWidget(self.advanced_metadata)
self.layout().addWidget(self.first_widget)
self.layout().addWidget(self.second_widget)
self.layout().addStretch()
self.resizeApp(650, self.sizeHint().height())
self.show()
# toggles advanced metadata view
def displayAdvanced(self):
if self.advanced_metadata.isChecked():
self.second_widget.setVisible(True)
self.second_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
self.resizeApp(650, self.sizeHint().height())
else:
self.second_widget.setHidden(True)
self.second_widget.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
self.resizeApp(650, self.sizeHint().height())
# resizes main window
def resizeApp(self, width, height):
self.resize(width, height)
print(self.size())
if __name__ == '__main__':
# accounts for exiting errors in python
if not QApplication.instance():
app = QApplication(sys.argv)
else:
app = QApplication.instance()
ex = App()
app.exec_()
I expect the size of the window when initialized to be 650x112, then when the Advanced
checkbox is selected the size should change to 650x149, and lastly, when the Advanced
checkbox is unchecked, the size should revert back to 650x112. The last expectation does not occur; instead, the window remains at 650x149.
Upvotes: 2
Views: 93
Reputation: 243887
In Qt many of the tasks are done asynchronously, and that is the case of geometry, so even if you have changed the policies this will not apply immediately until the synchronous part ends. So a workaround is to use QTimer.singleShot(0, ...)
to apply the resizing one instant later.
from functools import partial
from PyQt5 import QtCore, QtWidgets
class App(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.move(100, 100)
# main widgets
self.advanced_metadata = QtWidgets.QCheckBox(
"Advanced", stateChanged=self.displayAdvanced
)
self.first_widget = QtWidgets.QLabel("first_widget")
self.second_widget = QtWidgets.QLabel("second_widget")
self.second_widget.setHidden(True)
self.second_widget.setSizePolicy(
QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored
)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.advanced_metadata)
lay.addWidget(self.first_widget)
lay.addWidget(self.second_widget)
lay.addStretch()
self.resizeApp(650, self.sizeHint().height())
# toggles advanced metadata view
@QtCore.pyqtSlot(int)
def displayAdvanced(self, state):
if state == QtCore.Qt.Checked:
self.second_widget.show()
self.second_widget.setSizePolicy(
QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Preferred,
)
else:
self.second_widget.hide()
self.second_widget.setSizePolicy(
QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored
)
wrapper = partial(self.resizeApp, 650, self.sizeHint().height())
QtCore.QTimer.singleShot(0, wrapper)
@QtCore.pyqtSlot(int, int)
def resizeApp(self, width, height):
self.resize(width, height)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
Upvotes: 1