In Python how to pass the self between 2 windows using modules

Asked

Viewed 112 times

2

I’m learning Python, version 3.7 with Pyqt5 (Qt Designer)

I’m trying to define the value of a label using modules, in window 1 it calls the function and works, but when I open window 2 and click on the button it triggers the function but passes the self of the current window (window 2) where there is no label, generating the following error:

Traceback (most recent call last):
  File "\template\config.py", line 18, in returnMain
    fun1(self)
  File "\modulos\functions.py", line 7, in fun1
    lbl = int(self.ui.lblTest.text())
AttributeError: 'Ui_window2' object has no attribute 'lblTest'

I need it to use the self function of window 1.

I replicated the error in small files, it works until clicking the button of the second window that gives the described error.

Follow the code structure in the directory:

inserir a descrição da imagem aqui

Follow the files.

run.py (used to startar the program)

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
import sys

from template.main import MainScreen

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = MainScreen()
    main.show()

sys.exit(app.exec_())

Gui/window1.py (main window)

from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_window1(object):
    def setupUi(self, win1):
        win1.setObjectName("win1")
        win1.resize(297, 219)
        self.centralwidget = QtWidgets.QWidget(win1)
        self.centralwidget.setObjectName("centralwidget")
        self.btnConfig = QtWidgets.QPushButton(self.centralwidget)
        self.btnConfig.setGeometry(QtCore.QRect(110, 150, 75, 23))
        self.btnConfig.setObjectName("btnConfig")
        self.lblTest = QtWidgets.QLabel(self.centralwidget)
        self.lblTest.setGeometry(QtCore.QRect(120, 70, 47, 13))
        self.lblTest.setObjectName("lblTest")
        win1.setCentralWidget(self.centralwidget)

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

    def retranslateUi(self, win1):
        _translate = QtCore.QCoreApplication.translate
        win1.setWindowTitle(_translate("win1", "Window 1"))
        self.btnConfig.setText(_translate("win1", "Open config"))
        self.lblTest.setText(_translate("win1", "0"))

Gui/window2.py (settings window)

from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_window2(object):
    def setupUi(self, win2):
        win2.setObjectName("win2")
        win2.resize(222, 241)
        self.centralwidget = QtWidgets.QWidget(win2)
        self.centralwidget.setObjectName("centralwidget")
        self.btnReturn = QtWidgets.QPushButton(self.centralwidget)
        self.btnReturn.setGeometry(QtCore.QRect(70, 120, 75, 23))
        self.btnReturn.setObjectName("btnReturn")
        win2.setCentralWidget(self.centralwidget)

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

    def retranslateUi(self, win2):
        _translate = QtCore.QCoreApplication.translate
        win2.setWindowTitle(_translate("win2", "Window 2"))
        self.btnReturn.setText(_translate("win2", "Return Main"))

modulos/functions.py (where the functions will be)

from PyQt5.QtWidgets import *
from template import main

def fun1(self):
    lbl = int(self.ui.lblTest.text())
    lbl = (lbl+1)
    self.ui.lblTest.setText(str(lbl))

template/config.py (where I will handle settings)

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from gui.window2 import *
from modulos.functions import fun1

class ConfigScreen(QMainWindow):
   
    def __init__(self,*args,**argsv):        
        super(ConfigScreen,self).__init__(*args,**argsv)
        self.ui = Ui_window2()
        self.ui.setupUi(self)
        self.ui.btnReturn.clicked.connect(self.returnMain)

    def returnMain(self):
        fun1(self)
        self.close()

template/main.py (main module of the program)

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from gui.window1 import *
from template.config import ConfigScreen
from modulos.functions import fun1

class MainScreen(QMainWindow):
   
    def __init__(self,*args,**argsv):        
        super(MainScreen,self).__init__(*args,**argsv)
        self.ui = Ui_window1()
        self.ui.setupUi(self)
        self.ui.btnConfig.clicked.connect(self.openConfig)

        fun1(self)

    def openConfig(self):        
        self.config = ConfigScreen()
        self.config.show()

Remember, what is simple for you can be very difficult for others. I’m 1 week trying to solve and I can’t, I was programming a long time ago and I’m trying/needing to learn something new

  • 1

    Maurice, welcome to our community. I really liked his final sentence and, as my former director would say: "Everything is very easy for those who do nothing." Every beginning or resumption of a study requires a lot of effort and I hope you can achieve your goals there! You’ve worked it out very well and I’m sure someone will help you.

3 answers

1


you are trying to change an attribute that does not exist in the class Configscreen; the attribute lblTest belongs to your ui in class Mainscreen. When you call the bell func1(self) in class Mainscreen probably works because the self passed as parameter for the function is a reference to class Mainscreen or is the very instance of the class Mainscreen; already in class Configscreen when you call the same func1(self) you are passing the class reference Configscreen and function tries to change an attribute that does not exist; to change the attribute lblTest vc needs a reference of the main class to have access to this attribute; then create a parameter at class initialization Configscreen ex:

class ConfigScreen(QMainWindow):

def __init__(self,*args,**argsv, parent):        
    super(ConfigScreen,self).__init__(*args,**argsv, parent)
    self.parent = parent
    self.ui = Ui_window2()
    self.ui.setupUi(self)
    self.ui.btnReturn.clicked.connect(self.returnMain)

def returnMain(self):
    fun1(self.parent)
    self.close()

the self.Rent attribute takes the instance of the main class. And in the class Mainscreen Pass the self in the class instantiation Configscreen ex:

def openConfig(self):        
    self.config = ConfigScreen(self) # parent recebe o self como valor
    self.config.show()
  • Thanks @karllos, I was able to solve with your reply, had a small detail that generated another error but I was able to solve and shared as a response to help other people.

1

karlloss is right, in returnMain it is not necessary to pass the object to func1.

Perhaps the confusion lies in the understanding of the parameter self, it works much like the this in other languages such as Java or Javascript. It is a parameter of the class to which it belongs and exists only within that class. If you want to pass the properties of one class to another use the instantiated object itself and not the self.

Notice that here:

def fun1(self):
    lbl = int(self.ui.lblTest.text())
    lbl = (lbl+1)
    self.ui.lblTest.setText(str(lbl))

The argument self may, for example, have another name, since it is not part of any class.

Continue your studies, with practice some concepts will start to make more sense :)

0

I was able to solve it with the karlloss answer.

At first it had generated an error:

    def __init__(self,*args,**argsv, parent):
                                          ^
SyntaxError: invalid syntax

Researching a little I discovered that Parent should come before the other arguments:

class ConfigScreen(QMainWindow):

    def __init__(self, parent, *args, **argsv):        
        super(ConfigScreen,self).__init__(parent, *args,**argsv)
        self.parent = parent
        self.ui = Ui_window2()
        self.ui.setupUi(self)
        self.ui.btnReturn.clicked.connect(self.returnMain)

    def returnMain(self):
        fun1(self.parent)
        self.close()

After this little fix everything worked perfectly.

Many thanks to those involved.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.