QPushButton binding does not work without lambda keyword



  • Hello,
    i am facing a problem that i don't understand why it happen.

    When binding a QPushButton in a subclass method of my project

    #! python3
    # -*- coding: utf-8 -*-
    
    import sys
    import re
    
    from PySide2.QtWidgets import *
    from PySide2.QtCore import Qt, QRect, QCoreApplication
    from PySide2.QtGui import QIcon, QFont, QPixmap
    
    from FGIntMngtUI.FGIntMngtDeviceTab import Ui_FGIntMngtDeviceTab
    from FGIntMngtUI.FGIntMngtMCP23017Tab import Ui_FGIntMngtMCP23017Tab
    
    class FGIntMngtDevice():
        def __init__(self, item: QTreeWidgetItem, objectTab: QTabWidget, displayLog: QTextEdit):
            self.item = item
            self.devicename = self.item.text(0)
            self.deviceid = self.item.text(1)
            self.deviceaddr = self.item.text(2)
            self.devicetype = self.item.text(3)
            self.objecttab = objectTab
            self.displaylog = displayLog
            self.devicetabValueSteelSheet = "QLabel { font-size:12pt; }"
    
        ##### ##### ##### ##### ##### ##### ##### #####
        # Self String
        ##### ##### ##### ##### ##### ##### ##### #####
        def __str__(self):
            return "Device Objects Managements (FGIntMngtDevice Class)"
        
        def updateDevice(self):
            self.displaylog.append("test")
            print("test")
    
        def getDevice(self):
            self.objecttab.clear()
            self.displaylog.append("Getting Device .... {}".format(type(self.objecttab)))
            self.displaylog.append("Device Name {}".format(self.devicename))
            self.displaylog.append("Device Type {}".format(self.devicetype))
            self.displaylog.append("Device Addr {}".format(self.deviceaddr))
            self.currenttab = Ui_FGIntMngtDeviceTab()
            self.currenttab.setupUi(self.objecttab)
            self.currenttab.DeviceApplyBtn.clicked.connect(self.updateDevice)
            #self.currenttab.DeviceApplyBtn.clicked.connect(lambda: self.updateDevice())
            self.currenttab.DeviceTypeValue.setStyleSheet(self.devicetabValueSteelSheet)
            self.currenttab.DeviceIdValue.setStyleSheet(self.devicetabValueSteelSheet)
            self.currenttab.DeviceIdValue.setText(self.deviceid)
            self.currenttab.DeviceAddrValue.setStyleSheet(self.devicetabValueSteelSheet)
            self.currenttab.DeviceAddrValue.setText(self.deviceaddr)
            self.currenttab.DeviceNameValue.setStyleSheet(self.devicetabValueSteelSheet)
            self.currenttab.DeviceNameValue.setText(self.devicename)
            index = self.currenttab.DeviceTypeValue.findText(self.devicetype, Qt.MatchFixedString)
            if index >= 0:
                self.currenttab.DeviceTypeValue.setCurrentIndex(index)
    

    the line binding the button [ this does not work ]

    self.currenttab.DeviceApplyBtn.clicked.connect(self.updateDevice)
    

    but if i use the following code it work

    self.currenttab.DeviceApplyBtn.clicked.connect(lambda: self.updateDevice())
    

    I don't understand why i am oblige to use lambda here.
    The main scripts create the GUI with a .py file create from a .ui file designed with Qt Designer.
    The main scripts call some other class and ui class

    If needed i can post more code

    Regards

    Daweed


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    What version of PySide2 are you using ?
    How did you install it ?



  • Hello

    I am using pyside2 5.13.0
    and install it with the pip command

    pip3 install PySide2
    i am using python 3.7.2

    I am not sure that it's a pyside issue as if i am using for example the code to clear the displayLog widget [ QTextEdit object ] and no error are raised. The method updateDevice seems to just not be executed.

    self.currenttab.DeviceApplyBtn.clicked.connect(self.displayLog.clear)
    

    the binding work.

    I am asking myself if there is not a problem when "propagating" the variable [ QTabWidget ]. I'm probably doing something wrong but I can not understand what :)

    Here a view of the GUI

    GUI View

    The main windows is create in the main script

    #! python3
    # -*- coding: utf-8 -*-
    
    import sys
    import re
    import socket
    from PySide2.QtWidgets import *
    from PySide2.QtCore import Qt, QRect, QCoreApplication
    from PySide2.QtGui import QIcon, QFont, QPixmap
    
    # FarmerSoft Tools Lib
    from FGIntMngt.FGIntMngtConfig import FGIntMngtConfig
    from FGIntMngt.FGIntMngtClient import FGIntMngtClient
    from FGIntMngt.FGIntMngtObject import FGIntMngtObject
    
    # FGIntMngt UI Windows & Widgets
    from FGIntMngtUI.FGIntMngtMain import Ui_MainWindow
    from FGIntMngtUI.About import Ui_About
    
    class MainWindow(QMainWindow, Ui_MainWindow):
        ##### ##### ##### ##### ##### #####
        ##### MainWindow Constructor
        ##### ##### ##### ##### ##### #####
        def __init__(self):
            super(MainWindow, self).__init__()
    
            ##### ##### ##### ##### ##### ##### ##### #####
            ##### Main Windows Initialisation
            ##### ##### ##### ##### ##### ##### ##### #####
            self.setupUi(self)
    
            ##### ##### ##### ##### ##### ##### ##### #####
            ##### Properties
            ##### ##### ##### ##### ##### ##### ##### #####
            
            ##### ##### ##### ##### ##### ##### ##### #####
            ##### Steel Sheet
            ##### ##### ##### ##### ##### ##### ##### #####
            self.LabelSteelSheet = "QLabel { font: bold; }"
            self.conSteelSheet = "QLabel { font: bold; color: green; }"
            self.disconSteelSheet = "QLabel { font: bold; color: red; }"
    
            ##### FGIntMngt Configuration
            self.fgintmngtconfig = FGIntMngtConfig()
            self.fgintmngtconfig.readConfig('treeobjects.ini')
            self.treeBranches = self.fgintmngtconfig.loadBranch(self.objectsTree)
            self.logDisplay.clear()
            
            ##### FGIntMngt Object Tree
            self.fgintmngtobjects = FGIntMngtObject(self.objectsTree, self.objectTab, self.logDisplay)
    
            ##### FGIntMngt TCP CLient
            self.fgintmngtclient = FGIntMngtClient()
    
            ##### Tab Module
            
            ##### ##### ##### ##### ##### ##### ##### #####
            ##### Slots And Signals
            ##### ##### ##### ##### ##### ##### ##### #####
            
            ##### Main Window
            ##### ##### Menu File
            self.actionQuit.triggered.connect(self.quitGui)
    
            ##### ##### Menu Configuration
            self.actionReadDevices.triggered.connect(self.readDevices)
            
            ##### ##### Menu Help
            self.actionAbout.triggered.connect(self.showAbout)
    
            ##### Status Frame Binding
            self.connexionButton.clicked.connect(self.connectFGIntSrv)
            
            ##### Tree Frame Binding
            self.objectsTree.itemClicked.connect(self.fgintmngtobjects.getObject)
            
        def quitGui(self):
            self.fgintmngtclient.setConnStatus(0)
            self.close()
    
        def showAbout(self):
            ##### About UI
            self.about = QWidget()
            self.ui_about = Ui_About()
            self.ui_about.setupUi(self.about)
            self.about.show()
    
        def connectFGIntSrv(self):
            self.logDisplay.clear()
            self.logDisplay.append("Connexion Parameters : {}:{}".format(self.fgintmngtclient.getFGIntHost(), self.fgintmngtclient.getFGIntPort()))
            if self.fgintmngtclient.getConnStatus() == 0:
                self.logDisplay.append("ready to connect")
                if self.fgintmngtclient.connectServer() == 1:
                    self.logDisplay.append("Connection OK")
                    self.connstatusValue.setText('Connected')
                    self.connstatusValue.setStyleSheet(self.conSteelSheet)
                    self.connexionButton.setText('Disconnect')
                    data = self.fgintmngtclient.sock.recv(1024).decode("utf-8")
                    self.logDisplay.append(data)
                    self.readDevices()
                else:
                    self.logDisplay.append("Connection Failed")
                    self.fgintmngtclient.setConnStatus(0)
                    self.connstatusValue.setText('Not Connected')
                    self.connexionButton.setText('Connect')
                    self.connstatusValue.setStyleSheet(self.disconSteelSheet)
            else:
                self.logDisplay.append("Disconnection")
                self.fgintmngtclient.setConnStatus(0)
                self.connstatusValue.setText('Not Connected')
                self.connexionButton.setText('Connect')
                self.connstatusValue.setStyleSheet(self.disconSteelSheet)
                self.fgintmngtclient.sendCmd("exit\n", 1024)
    
        def readDevices(self):
            self.logDisplay.clear()
            self.logDisplay.append("Nb d elements a purger : {}".format(self.treeBranches['Devices']['widget'].childCount()))
            if self.treeBranches['Devices']['widget'].childCount() > 0:
                self.logDisplay.append("Cleaning Devices Branch ...")
                for i in reversed(range(self.treeBranches['Devices']['widget'].childCount())):
                    self.treeBranches['Devices']['widget'].removeChild(self.treeBranches['Devices']['widget'].child(i))
            if self.fgintmngtclient.getConnStatus() == 1:
                self.logDisplay.append("Listing devices from FG interface ...")
                datatab = self.fgintmngtclient.sendCmd("show devices\n", 1024).splitlines()
                #self.logDisplay.append("datatab Type : {}".format(type(datatab)))
                #self.logDisplay.append("datatab Length: {}".format(len(datatab)))
                devicenum = 1
                devices = datatab[0][1:-1].split(',')
                for device in devices:
                    for deviceaddr in device.split(' '):
                        if re.match("^\dx\d{2}$", deviceaddr[1:-1]):
                            self.logDisplay.append("New Device Found : {} at address {} Type : {}".format('device' + str(devicenum).zfill(2), deviceaddr[1:-1], 'Device'))
                            item = QTreeWidgetItem(self.treeBranches['Devices']['widget'], 0)
                            item.setText(0, 'device' + str(devicenum).zfill(2))
                            item.setText(1, 'item' + str(devicenum).zfill(2))
                            item.setText(2, deviceaddr[1:-1])
                            item.setText(3, 'Device')
                            item.setText(4, 'Unknow')
                            devicenum += 1
            else:
                self.logDisplay.append("Not Connected")
    
    
    
    ##### ##### ##### ##### ##### ##### ##### #####
    ##### Main Application Definition & Execution
    ##### ##### ##### ##### ##### ##### ##### #####
    def main():
        app = QApplication(sys.argv)
        main_window = MainWindow()
        main_window.show()
        sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main()
    

    When clicking on an item in the QTreeWidget, an object is creating with a FGIntMngtObject Class

    self.objectsTree.itemClicked.connect(self.fgintmngtobjects.getObject)
    

    The FGIntMngtObject Class

    #! python3
    # -*- coding: utf-8 -*-
    
    import sys
    
    from PySide2.QtWidgets import *
    from PySide2.QtCore import Qt, QRect, QCoreApplication
    from PySide2.QtGui import QIcon, QFont, QPixmap
    
    from FGIntMngt.FGIntMngtDevice import FGIntMngtDevice
    
    class FGIntMngtObject():
        def __init__(self, treeWidget: QTreeWidget, objectTab: QTabWidget, displayLog: QTextEdit):
            super(FGIntMngtObject, self).__init__()
            self.treeWidget = treeWidget
            self.objecttab = objectTab
            self.displaylog = displayLog
    
        ##### ##### ##### ##### ##### ##### ##### #####
        # Self String
        ##### ##### ##### ##### ##### ##### ##### #####
        def __str__(self):
            return "FGIntMngtObject Class"
    
        ##### ##### ##### ##### ##### ##### ##### #####
        # Class Methods
        ##### ##### ##### ##### ##### ##### ##### #####
        def getObject(self):
            # Debug Printing #
            #print("Getting Object from Tree ...")
            #print("Current Item : {}".format(self.treeWidget.currentItem()))
            #print("Item have {} Column(s) and {} Child(s)".format(self.treeWidget.currentItem().columnCount(), self.treeWidget.currentItem().childCount()))
            # End Debug Printing #
            if self.treeWidget.indexOfTopLevelItem(self.treeWidget.currentItem().parent()) != -1: # Check if obj is not a top level branch
                #for c in range(self.treeWidget.currentItem().columnCount()):
                #    print("Column {} Value {}".format(c, self.treeWidget.currentItem().text(c)))
                if self.treeWidget.currentItem().text(3) == 'Device':
                	#devicename, deviceaddr, devicetype, objectTab
                    element = FGIntMngtDevice(
                    	self.treeWidget.currentItem(),
                        self.objecttab,
                        self.displaylog
                        )
                    print("Nom de l'élément : {}".format(element.devicename))
                    element.getDevice()
    
        def updObject(self):
            print("Updating Object ....")
    

    And from that if the QTreeWiddgetItem is a 'Device' type a Device Object will be generated and the QTabWidget is populate via the FGIntMngtDevice Class

    Hopping that will help

    If needed , i can post UI python files

    Regards


  • Lifetime Qt Champion

    Can you rather post a minimal example that shows that behaviour ?


 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.