Search code examples
pythonpyqtqt-designerqpushbutton

Push Button in second window does not work


I am new to PyQt5 and have a simple code where one window opens another. The second window contains pushbutton, which after pressing should print a message "push button clicked". The pushbutton works when the second window is called separately and not from the mainwindow. However, when the second window is called by the mainwindow, the pushbutton does nothing.

Code:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(110, 30, 211, 111))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(140, 200, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.print_method)

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

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.label.setText(_translate("Form", "This is another Window"))
        self.pushButton.setText(_translate("Form", "PushButton"))

    def print_method(self):
        print("push button clicked")


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.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(300, 190, 191, 91))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.show_new_window)

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")

        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

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

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

    def show_new_window(self):

        self.Form = QtWidgets.QWidget()
        ui = Ui_Form()
        ui.setupUi(self.Form)
        self.Form.show()


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

Solution

  • It doesn't work because the ui object has no reference, so it gets deleted as soon as show_new_window returns. The result is that since the print_method function is a member of Ui_Form, it doesn't get called because that instance has been deleted.

    A possibility could be to make the ui an attribute of the QWidget:

        def show_new_window(self):
            self.Form = QtWidgets.QWidget()
            self.Form.ui = Ui_Form()
            self.Form.ui.setupUi(self.Form)
            self.Form.show()
    

    In any case, be aware that manually editing files generated by pyuic (or trying to mimic their behavior) is considered bad practice and highly discouraged, as it might lead to confusion and unexpected behavior. Read more about this topic on the official guidelines about using Designer.