Error when instantiating a class for the second time

Viewed 64

I'm new to python and PyQt and was developing my first app using it, and I've been stuck in a problem when trying to instantiate a class I made again. I've got the following error:

Traceback (most recent call last):
  File "ConfiguradorAnx.py", line 16, in <lambda>
     self.ProductInfo.clicked.connect(lambda: self.newWindow(InfoProduct))
TypeError: 'InfoProduct' object is not callable
Aborted

The code goes like this:

from PyQt5 import QtCore, QtGui, QtWidgets, uic
import sys

class StartWindow(QtWidgets.QMainWindow):   #This function should inherit the class
                                            #used to make the ui file  
    def __init__(self):
        super(StartWindow,self).__init__()   #Calling the QMainWindow constructor
        uic.loadUi('Janela_inicial.ui',self)

        #defining quit button from generated ui
        self.QuitButton = self.findChild(QtWidgets.QPushButton, 'QuitButton')
        self.QuitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)

        #defining product info button
        self.ProductInfo = self.findChild(QtWidgets.QPushButton, 'ProductInformation')
        self.ProductInfo.clicked.connect(lambda: self.newWindow(InfoProduct))
        self.show() #Show the start window

    def newWindow(self, _class):
        self.newWindow = _class()
        del self.newWindow

class InfoProduct(QtWidgets.QMainWindow):
    def __init__(self):
        super(InfoProduct,self).__init__()
        uic.loadUi('informacao_prod.ui',self)
        self.QuitButton = self.findChild(QtWidgets.QPushButton, 'pushButton')
        self.QuitButton.clicked.connect(lambda: self.destroy())
        self.show()

def main():
    app = QtWidgets.QApplication(sys.argv)  #Creates a instance of Qt application
    InitialWindow = StartWindow()
    app.exec_() #Start application

if __name__ == '__main__':
    main()

The first time I click on self.ProductInfo button it works and the InfoProduct window opens, but when I close the window and click on the same button again, I've got the error. I can't figure out what is it that I'm missing, I hope you guys could help!

Cheers!

1 Answers

You're overwriting the newWindow function in its execution:

def newWindow(self, _class):
    self.newWindow = _class()

By doing this, the result is that the next time you click the button, the lambda will try to call self.newWindow(InfoProduct), but at that point self.newWindow is an instance of InfoProduct, which obviously is not callable.

The solution is simple (and very important) use different names for the function and the variable that points to the instance:

        self.ProductInfo.clicked.connect(lambda: self.createNewWindow(InfoProduct))

    def createNewWindow(self, _class):
        self.newWindow = _class()

Two small side notes:

  • There's no need to use findChild, as loadUi already creates python instance attributes for widgets: you already can access self.QuitButton, etc.
  • Avoid using capitalized names for variables and attributes. Read more about this and other code styling suggestions on the Style Guide for Python Code (aka, PEP-8).
Related