如何根据 PyQt5 Python 中的 window 大小调整 PyQt5 堆叠小部件的大小?

How to resize a PyQt5 stacked widget as per window size in PyQt5 Python?

我正在 qt-desginer 中设计一个 ui。我必须创建一个 UI,它有一个带有按钮的侧面菜单栏,无论按下哪个按钮,其相应的数据都会显示在右侧。

为了设计这个,我在中央小部件的 horizontal layout 中放置了两个 QFrame。我减少了名为 side_menu_bar 的左侧 QFrame 的宽度,因此它已成为侧面菜单栏。在右侧QFrame 名为content_area,我放了一个stackedWidget 多页

现在我想在 stackedWidget 上显示的任何数据都必须覆盖 content_area 的整个区域,因此我在 stackedWidget 上使用了 vertical layout。在stackedWidgetpage_2上,我放了一个tablewidget。如果用户单击侧面菜单栏上的 pushButton,将显示此 page_2

下面是 UI 文件的 python 代码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'home2.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_home_window(object):
    def setupUi(self, home_window):
        home_window.setObjectName("home_window")
        home_window.resize(1216, 613)
        self.centralwidget = QtWidgets.QWidget(home_window)
        self.centralwidget.setObjectName("centralwidget")
        self.layoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.layoutWidget.setGeometry(QtCore.QRect(2, 0, 1211, 611))
        self.layoutWidget.setObjectName("layoutWidget")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.layoutWidget)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.side_menu_bar = QtWidgets.QFrame(self.layoutWidget)
        self.side_menu_bar.setMinimumSize(QtCore.QSize(0, 0))
        self.side_menu_bar.setMaximumSize(QtCore.QSize(120, 16777215))
        self.side_menu_bar.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.side_menu_bar.setFrameShadow(QtWidgets.QFrame.Raised)
        self.side_menu_bar.setObjectName("side_menu_bar")
        self.pushButton = QtWidgets.QPushButton(self.side_menu_bar)
        self.pushButton.setGeometry(QtCore.QRect(20, 100, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout_2.addWidget(self.side_menu_bar)
        self.content_area = QtWidgets.QFrame(self.layoutWidget)
        self.content_area.setStyleSheet("background-color: rgb(170, 255, 0);")
        self.content_area.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.content_area.setFrameShadow(QtWidgets.QFrame.Raised)
        self.content_area.setObjectName("content_area")
        self.verticalLayoutWidget = QtWidgets.QWidget(self.content_area)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(9, 9, 1071, 591))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.stackedWidget = QtWidgets.QStackedWidget(self.verticalLayoutWidget)
        self.stackedWidget.setObjectName("stackedWidget")
        self.page = QtWidgets.QWidget()
        self.page.setObjectName("page")
        self.stackedWidget.addWidget(self.page)
        self.page_2 = QtWidgets.QWidget()
        self.page_2.setObjectName("page_2")
        self.tableWidget = QtWidgets.QTableWidget(self.page_2)
        self.tableWidget.setGeometry(QtCore.QRect(0, 0, 1071, 591))
        self.tableWidget.setRowCount(50)
        self.tableWidget.setColumnCount(50)
        self.tableWidget.setObjectName("tableWidget")
        self.stackedWidget.addWidget(self.page_2)
        self.verticalLayout.addWidget(self.stackedWidget)
        self.horizontalLayout_2.addWidget(self.content_area)
        home_window.setCentralWidget(self.centralwidget)

        self.retranslateUi(home_window)
        QtCore.QMetaObject.connectSlotsByName(home_window)

    def retranslateUi(self, home_window):
        _translate = QtCore.QCoreApplication.translate
        home_window.setWindowTitle(_translate("home_window", "MainWindow"))
        self.pushButton.setText(_translate("home_window", "PushButton"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    home_window = QtWidgets.QMainWindow()
    ui = Ui_home_window()
    ui.setupUi(home_window)
    home_window.show()
    sys.exit(app.exec_())

以下是我在app.py

中的使用方式
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from src.home2_ui import Ui_home_window


class HomeWindow(QMainWindow, Ui_home_window):
    def __init__(self):
        QMainWindow.__init__(self)
        self.home_ui = Ui_home_window()
        self.home_ui.setupUi(self)
        self.showMaximized()

        layout = self.home_ui.horizontalLayout_2
        self.home_ui.centralwidget.setLayout(layout)

        self.home_ui.pushButton.clicked.connect(self.show_page2)

    def show_page2(self):
        layout2 = self.home_ui.verticalLayout
        layout2.addWidget(self.home_ui.stackedWidget)
        self.home_ui.content_area.setLayout(layout2)


app = QApplication(sys.argv)
main_window = HomeWindow()
main_window.show()
sys.exit(app.exec_())

现在,根据我的理解,我想全屏显示我的应用程序并适合 window 的整个区域。因此,为此我将 horizontal layout 附加到 central widget:

layout = self.home_ui.horizontalLayout_2
self.home_ui.centralwidget.setLayout(layout)

现在为了让 table 小部件覆盖堆叠小部件的完整区域,我在按钮按下事件中使用了以下代码:

layout2 = self.home_ui.verticalLayout
layout2.addWidget(self.home_ui.stackedWidget)
self.home_ui.content_area.setLayout(layout2)

根据我的理解,我们想要在堆叠小部件中显示的任何小部件都必须覆盖堆叠小部件的整个区域,因此我将堆叠小部件附加到垂直布局,然后我将内容区域的布局设置为 layout2(这是垂直布局)。现在这样做,如果我单击按钮显示 table 小部件,则不会显示任何内容:

这里我有一个问题,当我点击按钮显示 table 小部件时,table 小部件没有显示,而是显示一个空白的 window,它也覆盖了侧面菜单栏。?

如果我将上面的代码替换为:

layout2 = self.home_ui.verticalLayout
layout2.addWidget(self.home_ui.tableWidget)
self.home_ui.content_area.setLayout(layout2)

所以在这种情况下,我将 table 小部件添加到垂直布局而不是堆叠小部件。下面是输出:

确实显示了 table,但只显示了半个屏幕。它还删除了侧面菜单栏。

我无法完全理解如何在使用 stacked widgets 时使用 layout。谁能指导我如何做到这一点。请帮忙。谢谢

这里是link下载home2.ui文件

更新:

我终于能够解决这个问题。我使用水平布局作为基本布局,它有两个 childrens content areaside menu barcontent areaside menu bar 都有垂直布局。在 side menu bar 中,我可以添加任意数量的内容,并且由于垂直布局,它会自动对齐。在 content area 中,我添加了堆叠小部件,这又是一个 child 的垂直布局。在堆叠小部件的第 2 页中,我不得不添加另一个垂直布局,然后添加 table 小部件。现在显示完美了。

全部代码如下:

UI 代码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'home5.ui'
#
# Created by: PyQt5 UI code generator 5.15.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_home_window(object):
    def setupUi(self, home_window):
        home_window.setObjectName("home_window")
        home_window.resize(1196, 573)
        self.centralwidget = QtWidgets.QWidget(home_window)
        self.centralwidget.setObjectName("centralwidget")
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(10, 10, 1181, 561))
        self.widget.setObjectName("widget")
        self.base_h_layout = QtWidgets.QHBoxLayout(self.widget)
        self.base_h_layout.setContentsMargins(0, 0, 0, 0)
        self.base_h_layout.setSpacing(0)
        self.base_h_layout.setObjectName("base_h_layout")
        self.side_menu_bar = QtWidgets.QFrame(self.widget)
        self.side_menu_bar.setMaximumSize(QtCore.QSize(120, 16777215))
        self.side_menu_bar.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.side_menu_bar.setFrameShadow(QtWidgets.QFrame.Raised)
        self.side_menu_bar.setObjectName("side_menu_bar")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.side_menu_bar)
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_2.setSpacing(0)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.menu_bar_v_layout = QtWidgets.QVBoxLayout()
        self.menu_bar_v_layout.setContentsMargins(10, 10, 10, 10)
        self.menu_bar_v_layout.setSpacing(10)
        self.menu_bar_v_layout.setObjectName("menu_bar_v_layout")
        self.pushButton = QtWidgets.QPushButton(self.side_menu_bar)
        self.pushButton.setObjectName("pushButton")
        self.menu_bar_v_layout.addWidget(self.pushButton)
        self.verticalLayout_2.addLayout(self.menu_bar_v_layout)
        self.base_h_layout.addWidget(self.side_menu_bar)
        self.content_area = QtWidgets.QFrame(self.widget)
        self.content_area.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.content_area.setFrameShadow(QtWidgets.QFrame.Raised)
        self.content_area.setObjectName("content_area")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.content_area)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.content_area_v_layout = QtWidgets.QVBoxLayout()
        self.content_area_v_layout.setSpacing(0)
        self.content_area_v_layout.setObjectName("content_area_v_layout")
        self.stackedWidget = QtWidgets.QStackedWidget(self.content_area)
        self.stackedWidget.setObjectName("stackedWidget")
        self.page = QtWidgets.QWidget()
        self.page.setObjectName("page")
        self.stackedWidget.addWidget(self.page)
        self.page_2 = QtWidgets.QWidget()
        self.page_2.setObjectName("page_2")
        self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.page_2)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.table_v_layout = QtWidgets.QVBoxLayout()
        self.table_v_layout.setSpacing(0)
        self.table_v_layout.setObjectName("table_v_layout")
        self.tableWidget = QtWidgets.QTableWidget(self.page_2)
        self.tableWidget.setRowCount(50)
        self.tableWidget.setColumnCount(50)
        self.tableWidget.setObjectName("tableWidget")
        self.table_v_layout.addWidget(self.tableWidget)
        self.verticalLayout_4.addLayout(self.table_v_layout)
        self.stackedWidget.addWidget(self.page_2)
        self.content_area_v_layout.addWidget(self.stackedWidget)
        self.verticalLayout.addLayout(self.content_area_v_layout)
        self.base_h_layout.addWidget(self.content_area)
        home_window.setCentralWidget(self.centralwidget)

        self.retranslateUi(home_window)
        QtCore.QMetaObject.connectSlotsByName(home_window)

    def retranslateUi(self, home_window):
        _translate = QtCore.QCoreApplication.translate
        home_window.setWindowTitle(_translate("home_window", "MainWindow"))
        self.pushButton.setText(_translate("home_window", "PushButton"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    home_window = QtWidgets.QMainWindow()
    ui = Ui_home_window()
    ui.setupUi(home_window)
    home_window.show()
    sys.exit(app.exec_())

app.py:

class HomeWindow(QMainWindow, Ui_home_window):
    def __init__(self):
        QMainWindow.__init__(self)
        self.home_ui = Ui_home_window()
        self.home_ui.setupUi(self)
        self.showMaximized()

        base_layout = self.home_ui.base_h_layout
        self.home_ui.centralwidget.setLayout(base_layout)

        side_menu_v_layout = self.home_ui.menu_bar_v_layout
        self.home_ui.side_menu_bar.setLayout(side_menu_v_layout)

        content_v_layout = self.home_ui.content_area_v_layout
        self.home_ui.content_area.setLayout(content_v_layout)

        table_layout = self.home_ui.table_v_layout
        self.home_ui.page_2.setLayout(table_layout)

        self.home_ui.pushButton.clicked.connect(self.show_page2)

    def show_page2(self):
        self.home_ui.stackedWidget.setCurrentWidget(self.home_ui.page_2)

这就是 qt-designer object 检查员的样子:

感谢@allec 和@musicamante。

side_menu_bar 没有出现,因为它没有布局管理器来确定合适的大小。即使您将子按钮直接添加到框架,它也不会相应地调整大小,除非您明确告诉它。您有很多额外的占位符 QWidget,尤其是 layoutWidgetverticalLayoutWidgetpage_2,它们使该设计变得比必要的更复杂。任何类型的小部件都可以直接添加到布局或堆叠小部件中。这两个 QFrame 应该各自有一个只包含子部件的布局。

class Ui_home_window(object):
    def setupUi(self, home_window):
        home_window.setObjectName("home_window")
        home_window.resize(1216, 613)
        self.centralwidget = QtWidgets.QWidget(home_window)
        self.centralwidget.setObjectName("centralwidget")
        
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.side_menu_bar = QtWidgets.QFrame()
        self.side_menu_bar.setMinimumSize(QtCore.QSize(0, 0))
        self.side_menu_bar.setMaximumSize(QtCore.QSize(120, 16777215))
        self.side_menu_bar.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.side_menu_bar.setFrameShadow(QtWidgets.QFrame.Raised)
        self.side_menu_bar.setObjectName("side_menu_bar")
        self.pushButton = QtWidgets.QPushButton(self.side_menu_bar)
        self.pushButton.setObjectName("pushButton")
        vbox = QtWidgets.QVBoxLayout(self.side_menu_bar)
        vbox.addWidget(self.pushButton)
        self.horizontalLayout_2.addWidget(self.side_menu_bar)
        
        self.content_area = QtWidgets.QFrame()
        self.content_area.setStyleSheet("background-color: rgb(170, 255, 0);")
        self.content_area.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.content_area.setFrameShadow(QtWidgets.QFrame.Raised)
        self.content_area.setObjectName("content_area")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.content_area)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.stackedWidget = QtWidgets.QStackedWidget()
        self.stackedWidget.setObjectName("stackedWidget")
        self.page = QtWidgets.QWidget()
        self.page.setObjectName("page")
        self.stackedWidget.addWidget(self.page)
        self.tableWidget = QtWidgets.QTableWidget()
        self.tableWidget.setRowCount(50)
        self.tableWidget.setColumnCount(50)
        self.tableWidget.setObjectName("tableWidget")
        self.stackedWidget.addWidget(self.tableWidget)
        self.verticalLayout.addWidget(self.stackedWidget)
        self.horizontalLayout_2.addWidget(self.content_area)
        home_window.setCentralWidget(self.centralwidget)

        self.retranslateUi(home_window)
        QtCore.QMetaObject.connectSlotsByName(home_window)

    def retranslateUi(self, home_window):
        _translate = QtCore.QCoreApplication.translate
        home_window.setWindowTitle(_translate("home_window", "MainWindow"))
        self.pushButton.setText(_translate("home_window", "PushButton"))

HomeWindow中的小部件无需进一步设置布局,您可以通过QStackedWidget.setCurrentIndex()切换到其他页面。

class HomeWindow(QMainWindow, Ui_home_window):
    def __init__(self):
        QMainWindow.__init__(self)
        self.home_ui = Ui_home_window()
        self.home_ui.setupUi(self)
        self.showMaximized()

        self.home_ui.pushButton.clicked.connect(self.show_page2)

    def show_page2(self):
        self.home_ui.stackedWidget.setCurrentIndex(1)

按下按钮之前:

按下按钮后: