Home > front end >  Why does my second window have a different layout?
Why does my second window have a different layout?

Time:01-15

Using PyQt5, I am creating multiple windows. These windows should be able to change the view without popping new windows. However, when adding another window to the mainwindow with exactly the same layout and buttons, the window layouts differ.

What I want is to use exactly the same layout options as the Main window. My code can be found below:

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt
import sys

class mainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        # MAIN WINDOW SETTINGS
        self.central_widget = QtWidgets.QStackedWidget()
        self.setGeometry(400, 150, 1200, 700)
        self.setWindowTitle('Main window')
        
        # COMPOSE MAIN WINDOW
        self.settings = {'grid': {'row': [5,0,0,0,1], 'column': [1,3,1,1]}}
        self.grid = QtWidgets.QGridLayout()
        self.grid.setVerticalSpacing(20)
        for row, stretch in enumerate(self.settings['grid']['row']):
            self.grid.setRowStretch(row, stretch)
        for column, stretch in enumerate(self.settings['grid']['column']):
            self.grid.setColumnStretch(column, stretch)
            
        self.b1 = QtWidgets.QPushButton("Button 1")
        self.b1.clicked.connect(lambda: self.b1_handler('second window'))
        self.b2 = QtWidgets.QPushButton("Button 2")
        self.b2.clicked.connect(self.b2_handler)
        self.b3 = QtWidgets.QPushButton("Button 3")
        self.b3.clicked.connect(self.b3_handler)
        self.b4 = QtWidgets.QPushButton("Button 4")
        self.b4.clicked.connect(self.b4_handler)
        self.b5 = QtWidgets.QPushButton("Button 5")
        self.b5.clicked.connect(self.b5_handler)       
        
        self.grid.addWidget(self.b1, 1, 1)
        self.grid.addWidget(self.b2, 1, 2)
        self.grid.addWidget(self.b3, 2, 1)
        self.grid.addWidget(self.b4, 3, 1)
        self.grid.addWidget(self.b5, 4, 3)
        
        self.main_window = QtWidgets.QWidget()
        self.main_window.setLayout(self.grid)
        
        # TEST WINDOW
        self.second_window = Second_window(self)
        
        # FINISH MAIN WINDOW AND SHOW INITIAL SCREEN
        self.central_widget.addWidget(self.main_window)
        self.central_widget.addWidget(self.second_window)
        self.setCentralWidget(self.central_widget)
        self.current_window = self.main_window
    def b1_handler(self, to_window):
        if to_window == 'second window':
            self.current_window.hide()
            self.second_window.show()
            self.current_window = self.second_window
        elif to_window == 'main window':
            self.current_window.hide()
            self.main_window.show()
            self.current_window = self.main_window
            
    def b2_handler(self):
        pass
    def b3_handler(self):
        pass
    def b4_handler(self):
        pass
    def b5_handler(self):
        pass

class Second_window(QtWidgets.QWidget):
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        # Create grid
        self.settings = {'grid': {'row': [5,0,0,0,1], 'column': [1,3,1,1]}}
        self.grid = QtWidgets.QGridLayout()        
        self.grid.setVerticalSpacing(20)
        for row, stretch in enumerate(self.settings['grid']['row']):
            self.grid.setRowStretch(row, stretch)
        for column, stretch in enumerate(self.settings['grid']['column']):
            self.grid.setColumnStretch(column, stretch)
        
        # CREATE WIDGETS ON PAGE
        self.b1 = QtWidgets.QPushButton("Button 1")
        self.b1.clicked.connect(self.b1_handler)
        self.b2 = QtWidgets.QPushButton("Button 2")
        self.b2.clicked.connect(self.b2_handler)
        self.b3 = QtWidgets.QPushButton("Button 3")
        self.b3.clicked.connect(self.b3_handler)
        self.b4 = QtWidgets.QPushButton("Button 4")
        self.b4.clicked.connect(self.b4_handler)
        self.b5 = QtWidgets.QPushButton("Button 5")
        self.b5.clicked.connect(self.b5_handler)
        
        self.grid.addWidget(self.b1, 1, 1)
        self.grid.addWidget(self.b2, 1, 2)
        self.grid.addWidget(self.b3, 2, 1)
        self.grid.addWidget(self.b4, 3, 1)
        self.grid.addWidget(self.b5, 4 ,3)
        
        # SET LAYOUT
        self.setLayout(self.grid)
    def b1_handler(self):
        pass 
    def b2_handler(self):
        pass
    def b3_handler(self):
        pass
    def b4_handler(self):
        pass
    def b5_handler(self):
        self.parent.b1_handler('main window')

def main():
    app = QtWidgets.QApplication(sys.argv)
    App = mainWindow()
    App.show()
    # sys.exit(app.exec_())
    currentExitCode = app.exec_()

if __name__ == '__main__':
    main()

With this code, my windows looks like this:

Main window:

Main window

Second window:

second window

From the main window, I use button 1 to navigate to the second window. From the second window, I use button 5 to navigate back to the main window. What do I not understand properly?

CodePudding user response:

Forcing the visibility of widgets added to a QStackedWidget isn't the proper way to display them, as the stacked layout won't be notified about the change and will not be able to properly relay the resize events.

To switch between widgets you must use the functions provided by the class, as clearly explained in the main documentation of QStackedWidget:

The index of the widget that is shown on screen is given by currentIndex() and can be changed using setCurrentIndex(). In a similar manner, the currently shown widget can be retrieved using the currentWidget() function, and altered using the setCurrentWidget() function.

Change to:

    def b1_handler(self, to_window):
        if to_window == 'second window':
            self.central_widget.setCurrentWidget(self.second_window)
        elif to_window == 'main window':
            self.central_widget.setCurrentWidget(self.main_window)

You also don't need a reference to the current page, as currentWidget() already provides that dynamically.

  •  Tags:  
  • Related