I'm currently writing an PYQT5 GUI Application, where it is possible to switch between multiple widgets in the same Main Window. I'm using a QStackedWidget for that, where I've added all the other Widgets. For switching between them, I just set the current Widget of the QStackedWidget. The QStackedWidget is the central Widget of the Main Window. One of the Widgets available in the QStackedWidget has a QListWidget, where I can add multiple custom objects.
The Problem now is, if i add more than one object to the list and then try to change the current Widget of the QStackedWidget, the Application crashes with no error Message.
I'm using Pyqt 5 in Python 3.9.13.
Also I've written a code example, in which the described problem occures. I would really appreciated, if somebody could help me!
Reproduce the Error:
1.) Press the pushButton --> a new View shows up
2.) Add one Item to the List with the Button at the Bottom
3.) Press the pushButton at the Top --> FirstView shows up, everything works fine
4.) Press again the pushButton in the Center
5.) Add further Objects to the List
6.) Press the Button at the Top again --> the Application crashes with no error...
My example Code to reproduce the Error:
App
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import *
class App(QApplication):
def __init__(self, argv):
super().__init__(argv)
self.setApplicationName("Test")
self.setOrganizationName("Kai Industries")
Controller View 1
from PyQt5 import *
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from Ui_view1 import Ui_View1
from controller_view2 import Controller_View2
class Controller_View1(QWidget, Ui_View1):
def __init__(self, main, model,previous):
super().__init__(main)
QWidget.__init__(self)
Ui_View1.__init__(self)
self.setupUi(self)
self._main = main
self._model = model
self._previous = previous
self._main._controller_view2=Controller_View2(self._main,self._model,self)
self._main._central_widget.addWidget(self._main._controller_view2)
self.pushButton_forward.clicked.connect(self.execute_forward)
def execute_forward(self):
self._main._central_widget.setCurrentWidget(self._main._controller_view2)
Controller View 2
from PyQt5 import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from Ui_view2 import Ui_View2
from submodel import Submodel
from controller_widget_submodel import Controller_Widget_Submodel
class Controller_View2(QWidget, Ui_View2):
def __init__(self, main, model,previous):
super().__init__(main)
QWidget.__init__(self)
Ui_View2.__init__(self)
self.setupUi(self)
self._main = main
self._model = model
self._previous = previous
self.pushButton_add.clicked.connect(self.execute_add)
self.pushButton_back.clicked.connect(self.execute_back)
def execute_add(self):
submodels = self._model.get_submodels()
submodel=Submodel()
submodel.set_value1=1
submodel.set_value2=2
submodels.insert(len(submodels),submodel)
self.actualize_list()
def execute_back(self):
self._main._central_widget.setCurrentWidget(self._previous)
def actualize_list(self):
self.listWidget.clear()
submodels = self._model.get_submodels()
i=0
for submodel in submodels:
list_widget_item = QListWidgetItem(self.listWidget)
controller_widget_submodel = Controller_Widget_Submodel(self._main,submodel)
list_widget_item.setSizeHint(controller_widget_submodel.sizeHint())
self.listWidget.insertItem(i,list_widget_item)
self.listWidget.setItemWidget(list_widget_item,controller_widget_submodel)
i=i+1
Controller widget for ListWidgetItem
from PyQt5 import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from Ui_widget_submodel import Ui_widget_submodel
class Controller_Widget_Submodel(QWidget, Ui_widget_submodel):
def __init__(self, main, model):
super().__init__(main)
QWidget.__init__(self)
Ui_widget_submodel.__init__(self)
self.setupUi(self)
self._main = main
self._model = model
self.label_value1.setText(self._model.get_value1())
self.label_value2.setText(self._model.get_value2())
Controller Main Window
from PyQt5 import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from controller_view1 import Controller_View1
from model import Model
class Controller_Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.showFullScreen()
self.setFixedSize(QSize(800,480))
self._model=Model()
self._central_widget = QStackedWidget()
self._controller_view1 = Controller_View1(self,self._model,self)
self._central_widget.addWidget(self._controller_view1)
self._central_widget.setCurrentWidget(self._controller_view1)
self.setCentralWidget(self._central_widget)
self.show()
Main
import sys
from PyQt5.QtCore import *
from app import *
from controller_window import Controller_Main
import cgitb
cgitb.enable(format = 'text')
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
if __name__ == "__main__":
sys.excepthook = lambda exctype, value, traceback: sys.__excepthook__(exctype, value, traceback)
app = App(sys.argv)
#if frozen: _MEIPASS path and every error as messagebox
try:
controller_main = Controller_Main()
sys.exit(app.exec())
except Exception as e:
QMessageBox.critical(None , "Error", "An Error occured: " + str(e))
Model
from submodel import Submodel
class Model():
def __init__(self):
self._submodels = list()
def add_submodel(self,submodel:Submodel):
self._submodels.append(submodel)
def get_submodels(self):
return self._submodels
Submodel
class Submodel():
def __init__(self):
self._value1="Test1"
self._value2="Test2"
def set_value1(self,value:int):
self._value1 = value
def set_value2(self,value:int):
self._value2 = value
def get_value2(self):
return self._value2
def get_value1(self):
return self._value1
Ui View 1
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_View1(object):
def setupUi(self, View1):
View1.setObjectName("View1")
View1.resize(400, 300)
self.verticalLayout = QtWidgets.QVBoxLayout(View1)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton_forward = QtWidgets.QPushButton(View1)
self.pushButton_forward.setObjectName("pushButton_forward")
self.verticalLayout.addWidget(self.pushButton_forward)
self.retranslateUi(View1)
QtCore.QMetaObject.connectSlotsByName(View1)
def retranslateUi(self, View1):
_translate = QtCore.QCoreApplication.translate
View1.setWindowTitle(_translate("View1", "Form"))
self.pushButton_forward.setText(_translate("View1", "PushButton"))
Ui View 2
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_View2(object):
def setupUi(self, View2):
View2.setObjectName("View2")
View2.resize(400, 300)
self.verticalLayout = QtWidgets.QVBoxLayout(View2)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton_back = QtWidgets.QPushButton(View2)
self.pushButton_back.setObjectName("pushButton_back")
self.verticalLayout.addWidget(self.pushButton_back)
self.listWidget = QtWidgets.QListWidget(View2)
self.listWidget.setObjectName("listWidget")
self.verticalLayout.addWidget(self.listWidget)
self.pushButton_add = QtWidgets.QPushButton(View2)
self.pushButton_add.setObjectName("pushButton_add")
self.verticalLayout.addWidget(self.pushButton_add)
self.retranslateUi(View2)
QtCore.QMetaObject.connectSlotsByName(View2)
def retranslateUi(self, View2):
_translate = QtCore.QCoreApplication.translate
View2.setWindowTitle(_translate("View2", "Form"))
self.pushButton_back.setText(_translate("View2", "Back"))
self.pushButton_add.setText(_translate("View2", "Add"))
Ui submodel
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_widget_submodel(object):
def setupUi(self, widget_submodel):
widget_submodel.setObjectName("widget_submodel")
widget_submodel.resize(120, 33)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(widget_submodel)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_value1 = QtWidgets.QLabel(widget_submodel)
self.label_value1.setObjectName("label_value1")
self.horizontalLayout.addWidget(self.label_value1)
self.label_value2 = QtWidgets.QLabel(widget_submodel)
self.label_value2.setObjectName("label_value2")
self.horizontalLayout.addWidget(self.label_value2)
self.horizontalLayout_2.addLayout(self.horizontalLayout)
self.retranslateUi(widget_submodel)
QtCore.QMetaObject.connectSlotsByName(widget_submodel)
def retranslateUi(self, widget_submodel):
_translate = QtCore.QCoreApplication.translate
widget_submodel.setWindowTitle(_translate("widget_submodel", "Form"))
self.label_value1.setText(_translate("widget_submodel", "TextLabel"))
self.label_value2.setText(_translate("widget_submodel", "TextLabel"))
Ui Main Window
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout_2.setObjectName("verticalLayout_2")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))