0

Note: I've edited my question for better understanding.

I have a code works well. But there is something I do not understand exactly.


import sys

from PyQt5 import QtCore,  QtWidgets

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):

        MainWindow.setObjectName("MainWindow")
        MainWindow.setWindowTitle("TEST PROGRAM")
        MainWindow.resize(1000, 700)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(MainWindow)

        self.tabWidget.setGeometry(QtCore.QRect(20, 20, 1880, 950))
        self.tabWidget.setAutoFillBackground(False)
        self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded)
        self.tabWidget.setObjectName("tabWidget")

        PreparePanel(self.tabWidget,"myPanel","TEST")

        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


class PreparePanel():

    def __init__(self,twg,panelName,panelbaslik):

        self.myPanel = QtWidgets.QWidget()
        self.myPanel.setObjectName(panelName)
        twg.addTab(self.myPanel, panelbaslik)
        self.LEdit = QtWidgets.QLineEdit(self.myPanel)
        self.LEdit.setGeometry(QtCore.QRect(2, 95, 100, 22))  
        self.LEdit.setFrame(True)
        self.LEdit.setObjectName("LEdit_0")

#---------------works fine------------------------------------------------------
    #For the code to work, we need to use a dummy variable.
        self.LEdit.textChanged.connect(lambda dummyvar: self.myFilterFunc(dummyvar))

    def myFilterFunc(self,dummyVariable):
        child = self.myPanel.findChild(QtWidgets.QLineEdit, "LEdit_0")
        print(child.text())
#---------------works fine------------------------------------------------------

#--------------- does not work------------------------------------------------------
    #When we replace the above section with this section, the code does not work.
    #     
    #     self.LEdit.textChanged.connect(self.myFilterFunc)
    # def myFilterFunc(self):
    #     child = self.myPanel.findChild(QtWidgets.QLineEdit, "LEdit_0")
    #     print(child.text())


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    pencere = QtWidgets.QWidget()
    AnaPencere = Ui_MainWindow()
    AnaPencere.setupUi(pencere)
    pencere.show()
    sys.exit(app.exec_())

I do not use cond_text parameter in myFilterFunc(), but when I remove that parameter, code doesn't work and raise error like:

AttributeError: 'NoneType' object has no attribute 'text'

Why should I put a parameter that I never used?

Thanks in advance.

If we put the function at the beginning of init(), the lambda is not needed. Also if we remove PrepareClass and put the code inside PrepareClass into Class Ui_MainWindow(object), the code still works even though myFilterFunc() is outside the setupUi function. But I do not understand why?

Another working code.

import sys
from PyQt5 import QtCore,  QtWidgets

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):

        MainWindow.setObjectName("MainWindow")
        MainWindow.setWindowTitle("TEST")
        MainWindow.resize(1000, 700)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(MainWindow)

        self.tabWidget.setGeometry(QtCore.QRect(20, 20, 1880, 950))
        self.tabWidget.setAutoFillBackground(False)
        self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded)
        self.tabWidget.setObjectName("tabWidget")

        
        self.LEdit = QtWidgets.QLineEdit(self.tabWidget)
        self.LEdit.setGeometry(QtCore.QRect(100, 100, 150, 30))       
        self.LEdit.setFrame(True)
        self.LEdit.setObjectName("LEdit_1")

        self.LEdit.textChanged.connect(self.myFilterFunc)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


    def myFilterFunc(self):

        child = self.tabWidget.findChild(QtWidgets.QLineEdit, "LEdit_1")
        
        print(child.text())



if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    pencere = QtWidgets.QWidget()
    AnaPencere = Ui_MainWindow()
    AnaPencere.setupUi(pencere)
    pencere.show()
    sys.exit(app.exec_())
MacKey
  • 45
  • 5
  • You call `myfilterfunc` with the argument text in `dosomething()`. `self` is an instance variable not a "real" argument of a function. – Gábor Erdős Aug 08 '22 at 11:31
  • Remove `()` in your second `connect`. – zigma12 Aug 08 '22 at 11:34
  • Removing ```()``` does not work. When it removed then ```connect``` does not call the function. – MacKey Aug 08 '22 at 12:03
  • Your code has many issues. For instance, `i` is never declared, so I assume you're trying to access a global (which is wrong) or you didn't provide enough code, but in any case it won't work because, clearly, there is *no* QLineEdit that has an object name that results from that string formatting. Then, if you're not using that parameter, you shouldn't have called the function with that parameter: remove the argument and just use the second `connect` line you commented **without** the parentheses (signal connections use *callables*, but you're actually calling the function). – musicamante Aug 08 '22 at 12:06
  • If you want useful help, [edit] your question and provide a *real* [mre]. – musicamante Aug 08 '22 at 12:07
  • 1
    THis is a very common problem caused by failing to keep a reference to the object which owns the slot the signal is connected to. In this case, a simple fix is to do `self.panel = PreparePanel(self.tabWidget, "myPanel", "TEST")`. The reason why the `lambda` works is that it forms closure over `self`, which keeps the instance of `PreparePanel` alive. Otherwise, the signal connection will be automatically broken when the instance is garbage-collected. – ekhumoro Aug 09 '22 at 09:48
  • @MacKey Do not ever use `findChild` to access widgets defined in Qt Designer. It's error-prone, ugly and totally unnecessary. The slot should either be defined like this `def myFilterFunc(self): print(self.LEdit.text())` or like this `def myFilterFunc(self, text): print(text)`. – ekhumoro Aug 09 '22 at 09:56
  • You are right, but I had to use this method because there are many QLineEdit objects. – MacKey Aug 09 '22 at 12:50

2 Answers2

0

Well for one, when you call the function you're passing text. Now I don't really get what your code does since you haven't included much, however I imagine taking text out of the parameters in the call should fix your issue.

Marco Kurepa
  • 325
  • 1
  • 9
0

Here the ontextchange signal is unable to make connection with the myfilterfunc(). So a possible way out is to add all the function inside the init() and use the lambda function to send signal to them.

import sys

from PyQt5 import QtCore,  QtWidgets

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):

        MainWindow.setObjectName("MainWindow")
        MainWindow.setWindowTitle("TEST PROGRAM")
        MainWindow.resize(1000, 700)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(MainWindow)

        self.tabWidget.setGeometry(QtCore.QRect(20, 20, 1880, 950))
        self.tabWidget.setAutoFillBackground(False)
        self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded)
        self.tabWidget.setObjectName("tabWidget")

        PreparePanel(self.tabWidget,"myPanel","TEST")

        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


class PreparePanel():

    def __init__(self,twg,panelName,panelbaslik):

        self.myPanel = QtWidgets.QWidget()
        self.myPanel.setObjectName(panelName)
        twg.addTab(self.myPanel, panelbaslik)
        self.LEdit = QtWidgets.QLineEdit(self.myPanel)
        self.LEdit.setGeometry(QtCore.QRect(2, 95, 100, 22))  
        self.LEdit.setFrame(True)
        self.LEdit.setObjectName("LEdit_0")

#---------------works fine------------------------------------------------------
        self.LEdit.textChanged.connect(lambda: myFilterFunc())
        def myFilterFunc():
            child = self.myPanel.findChild(QtWidgets.QLineEdit, "LEdit_0")
            print(child.text())



if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    pencere = QtWidgets.QWidget()
    AnaPencere = Ui_MainWindow()
    AnaPencere.setupUi(pencere)
    pencere.show()
    sys.exit(app.exec_())
Hamza
  • 132
  • 5
  • If we put the function at the beginning of init(), the lambda is not needed. Also if we remove PrepareClass and put the code inside PrepareClass into Class Ui_MainWindow(object), the code still works even though myFilterFunc() is outside the setupUi function. But I do not understand why? I have edited my question above. – MacKey Aug 09 '22 at 06:53