简体   繁体   中英

PyQt5: How to Resize mainwindow to fit a Stackedwidget or Stackedlayout

I have a MainWindow with a Dockwidget attached to it for the sole purpose of switching between multiple Stackedwidget/StackedLayout

The Issue i am having is that the StackedLayout holds a particular widget that displays a large image which resizes the MainWindow as expected but when switching from that Widget to another using the docked widget the MainWindow still uses the SizeHint from the large widget even after calling a MainWindow.Resize(stackedwidget) which leaves the window larger than necessary for the current widget in view

Here's the code:

from PyQt5 import QtCore, QtGui, QtWidgets

class Mainwindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(Mainwindow, self).__init__()

        # window setting
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)

        # window central widget
        self.centerwidget = QtWidgets.QWidget()
        self.setCentralWidget(self.centerwidget)

        # stack for page/widget management
        self.stack = QtWidgets.QStackedLayout(self.centerwidget)

        # widgets or page management
        self.widgeta = None
        self.dockWidget = None
        self.widgetb= None

    def pageManager(self, widget):

        # switching stack widgets 
        self.stack.setCurrentWidget(widget)
        widget.updateGeometry()
        widget.layout.update()
        self.centerwidget.updateGeometry()
        self.updateGeometry()
        self.resize(widget.layout.totalSizeHint())

    def load(self):
        # basically startup
        # stack settings
        self.widgeta= Widgeta()
        self.widgetb= Widgetb()
        self.stack.addWidget(self.widgeta)
        self.stack.addWidget(self.widgetb)
        self.stack.setStackingMode(QtWidgets.QStackedLayout.StackOne)
        self.stack.setCurrentWidget(self.widgeta)

        # dock widget
        self.dockWidget = Duck()
        self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.dockWidget)

        # show mainwindow
        self.show()

class Duck(QtWidgets.QDockWidget):
    def __init__(self, parent=None):
        super(Duck, self).__init__(parent)
        # create subwidget assign layout to subwidget
        self.dockCentralWidget = QtWidgets.QWidget()
        self.dockCentralWidgetlayout = QtWidgets.QHBoxLayout()
        self.dockCentralWidgetlayout.setContentsMargins(QtCore.QMargins(1,1,1,1))
        self.dockCentralWidgetlayout.setSpacing(1)
        self.dockCentralWidget.setLayout(self.dockCentralWidgetlayout)
        self.dockCentralWidget.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        self.setStyleSheet("background-color: #354465;")
        # subwidget elements
        self.Ui()
        # add subwidget and elements
        self.setWidget(self.dockCentralWidget)
        self.dockCentralWidgetlayout.addWidget(self.widgetAButton)
        self.dockCentralWidgetlayout.addWidget(self.widgetBButton)
        
    def Ui(self):
        # first button
        self.widgetAButton = QtWidgets.QPushButton('aaaa')
        self.widgetAButton.clicked.connect(lambda : self.clicker((self.widgetAButton, Window.widgeta)))
        # second button 
        self.widgetBButton = QtWidgets.QPushButton('bbbb')
        self.widgetBButton.clicked.connect(lambda : self.clicker((self.widgetBButton, Window.widgetb)))
    
    def clicker(self, arg):
        Window.pageManager(arg[1])

class Widgeta(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widgeta, self).__init__(parent)

        # sizing and layout
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self.layout = QtWidgets.QVBoxLayout()
        self.setLayout(self.layout)

        # widgets
        self.ui()
    
    def ui(self):
        # a check button
        self.goButton = QtWidgets.QPushButton()
        self.goButton.setObjectName('gobutton')
        self.goButton.setText('ccc')
        self.goButton.setMinimumSize(QtCore.QSize(400, 150))
        self.goButton.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        self.goButton.setStyleSheet(goButtonCSS)

        # label
        self.infoLabel = QtWidgets.QLabel()
        self.infoLabel.setObjectName('infolabel')
        self.infoLabel.setMinimumSize(QtCore.QSize(400, 250))
        self.infoLabel.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        self.infoLabel.setText('jjjj')
        self.infoLabel.setStyleSheet(topDisplayCSS)

        # add widgets to layout
        self.layout.addWidget(self.infoLabel)
        self.layout.addWidget(self.goButton, QtCore.Qt.AlignVCenter, QtCore.Qt.AlignHCenter)
        self.layout.setContentsMargins(QtCore.QMargins(0,0,0,0))

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    Window = Mainwindow()
    Window.load()
    sys.exit(app.exec_())

i Have also tried using a StackedWidget as the central widget and switching, same thing.

The QStackedLayout always uses its minimum size based on the largest minimum size of all its widgets. This also means that all widgets using a stacked layout behave in the same way: QStackedWidget and QTabWidget.

This is done by design, and it's the correct approach (otherwise the parent widget would always try to resize itself whenever a new "page" is set with a different minimum size)

The solution is to subclass the QStackedLayout (or the QStackedWidget) and override its minimumSize() ; if needed, sizeHint() could be overridden in the same fashion, but I wouldn't suggest it.

class StackedLayout(QtWidgets.QStackedLayout):
    def minimumSize(self):
        if self.currentWidget():
            s = self.currentWidget().minimumSize()
            if s.isEmpty():
                s = self.currentWidget().minimumSizeHint()
            return s
        return super().minimumSize()

Note that if you want to resize the main window to the minimum possible size you should use mainWindow.resize(mainWindow.minimumSizeHint()) , since a QMainWindow also has minimum size requirements depending on its extra widgets, like toolbars or, as in your case, dock widgets.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM