pythonpyqt5qt-designerqtablewidgetqstackedwidget

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


I am designing a ui in qt-desginer. I have to create a UI which has a side menu bar with buttons and whichever button is pressed, its appropriate data will be shown on right side.

To design this, I have I have placed two QFrame in horizontal layout on central widget. I have reduced the width of left side QFrame named side_menu_bar and thus it has become the side menu bar. On the right side QFrame named content_area, I have placed a stackedWidget with multiple pages.

Now whatever data I want to show on stackedWidget has to cover the complete area of content_area and thus I have used a vertical layout on stackedWidget. On the page_2 of stackedWidget, I have placed a tablewidget. This page_2 will be shown if a user clicks pushButton on side menu bar.

Below is the python code of the UI file:

# -*- 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_())

and below is how I am using it in 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_())

Now as per my understanding, I want to show my application full screen and want to fit the complete area of the window. So for that I have attached the horizontal layout to central widget:

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

Now in order to make table widget cover the complete area of stacked widget I have used below code on button press event:

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

As per my understanding whatever widget we want to show in stacked widget has to cover the complete area of stacked widget and thus I have attached stacked widget to vertical layout and then I have set the layout of content area to layout2 (which is vertical layout). Now by doing this, if I click on the button to show table widget, nothing is getting shown:

enter image description here

Here I have a question, when I click on pushbutton to show table widget, table widget is not shown but instead a blank window is shown which is also covering the side menu bar.?

If I replace the above code to:

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

so In this case I have added table widget to vertical layout instead of stacked widget. Below is the output:

enter image description here

It does shows table but only on half screen. Also it has removed the side menu bar too.

I am not able to fully understand how to use the layout when using stacked widgets. Can anyone please guide me on how to do this. Please help. Thanks

Here is the link to download the home2.ui file

enter image description here

enter image description here

Update:

I have finally been able to resolve this. I have used horizontal layout which is acting as a base layout and it has two childrens content area and side menu bar. Both content area and side menu bar have vertical layout. In side menu bar I can add as many as I want and it will be auto aligned due to vertical layout. In content area I have added stacked widget which is again a child of vertical layout. In page 2 of stacked widget, I had to add another vertical layout and then added table widget. Now it showing perfectly.

Below is all the code:

UI CODE:

# -*- 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)

and this is how the qt-designer object inspector looks like:

enter image description here

Thanks to @allec and @musicamante.


Solution

  • The side_menu_bar does not appear because it has no layout manager to determine a proper size. Even though you added a child button directly to the frame, it will not resize accordingly unless you explicitly tell it to. You have a lot of extra placeholder QWidgets, particularly layoutWidget, verticalLayoutWidget, and page_2 that are making this design more complicated than necessary. Any kind of widget can be added directly to the layout or stacked widget. The two QFrames should each have a layout only containing the child widgets.

    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"))
    

    There is no need to further set layouts to widgets in HomeWindow, you can switch to the other page with 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)
    

    Before pressing button:

    enter image description here

    After pressing button:

    enter image description here