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:
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 usingsetCurrentIndex()
. In a similar manner, the currently shown widget can be retrieved using thecurrentWidget()
function, and altered using thesetCurrentWidget()
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.