Shock-o-lot
Shock-o-lot

Reputation: 135

I can't get window to resize when I hide a widget

I found some code on here that shows an example of how you can get the window to resize when the widget is hidden, and it works for me. Here is the code:

from PyQt4 import QtCore, QtGui
import sys

class MainWindow(QtGui.QWidget):
    def __init__(self):
        self.app = QtGui.QApplication(sys.argv)
        super(MainWindow, self).__init__()

        self.button = QtGui.QPushButton('Show/Hide')
        self.button.setCheckable(True)
        self.frame = QtGui.QFrame()
        self.frame.setFixedHeight(100)
        self.layout = layout = QtGui.QVBoxLayout()
        layout2 = QtGui.QVBoxLayout()
        self.setLayout(layout)
        self.frame.setLayout(layout2)

        layout.addWidget(self.button)
        layout.addWidget(self.frame)
        layout.addStretch(1)
        layout2.addWidget(QtGui.QLabel('Yoyoyo'))

        self.button.toggled.connect(self.clickAction)

    def startup(self):
        self.show()
        sys.exit(self.app.exec_())

    def clickAction(self):
        checked = self.button.isChecked()
        if checked:
            self.frame.show()
        else:
            self.frame.hide()
        QtCore.QTimer.singleShot(0, self.resizeMe)

    def resizeMe(self):
        self.resize(self.minimumSizeHint())
if __name__ == "__main__":
    myApp = MainWindow()
    myApp.startup()

I then tried to modify this to match my existing code by separating the mainWindow class and the widget class. Here is the code that does that.

from PySide import QtGui,QtCore
import sys



class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.w = testW(self)
        self.setCentralWidget(self.w)
        self.show()



class testW(QtGui.QWidget):
    def __init__(self,parent):
        super(testW,self).__init__()
        self.parent = parent
        self.button = QtGui.QPushButton('Show/Hide')
        self.button.setCheckable(True)
        self.button.setChecked(True);
        self.frame = QtGui.QFrame()
        self.frame.setFixedHeight(100)
        self.layout = layout = QtGui.QVBoxLayout()
        layout2 = QtGui.QVBoxLayout()
        self.setLayout(layout)
        self.frame.setLayout(layout2)

        layout.addWidget(self.button)
        layout.addWidget(self.frame)
        layout.addStretch(1)
        layout2.addWidget(QtGui.QLabel('Yoyoyo'))

        self.button.toggled.connect(self.clickAction)

    def clickAction(self):
        checked = self.button.isChecked()
        if checked:
            self.frame.show()
        else:
            self.frame.hide()
        QtCore.QTimer.singleShot(0, self.resizeMe)

    def resizeMe(self):
        self.resize(self.minimumSizeHint())

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myApp = MainWindow()
    sys.exit(app.exec_())
    #time.sleep(1)

Running the first code does what I want it to. After I hide the widget, the window resizes to the correct size. The second implementation of the code does not shrink and expand the window when I hide and show the widget. Is this because the MainWindow is in a separate class?

Upvotes: 1

Views: 1754

Answers (1)

apatrushev
apatrushev

Reputation: 425

  1. Use size policies for your widgets. For your example you can change UI creation code as follows:
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.w = testW(self)
        self.w.setSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.MinimumExpanding
        )
        self.setCentralWidget(self.w)
        self.show()

Please note new setSizePolicy call which say Qt layout engine how to change the size of your widget according to its content.

  1. Unfortunately QMainWindow does not respect sizeHint automatically, but it is calculated properly, so you can adjustSize manually:
    def clickAction(self):
        checked = self.button.isChecked()
        if checked:
            self.frame.show()
        else:
            self.frame.hide()
        QtCore.QTimer.singleShot(0, self.parent.adjustSize)

You do not need to resize your widget itself, because it will be resized according to the policy. Even sizeHint will be calculated automatically so you need only to call adjustSize of QMainWindow.

PS: I used PySide2 instead of PySide so the imports are different a little bit:

from PySide2 import QtWidgets, QtCore

Upvotes: 5

Related Questions