0

was trying to understand https://wiki.python.org/moin/PyQt/Binding%20widget%20properties%20to%20Python%20variables :

"Binding widget properties to Python variables"

down below my modified code that took a while to me, but kind of visualize better what bind, example code, here, does:

def bind(objectName, propertyName, type):

    def getter(self):
        return type(self.findChild(QObject, objectName).property(propertyName).toPyObject())
    
    def setter(self, value):
        self.findChild(QObject, objectName).setProperty(propertyName, QVariant(value))
    
    return property(getter, setter)

my complete code is:

import sys

from PyQt5.QtWidgets import QWidget, QLineEdit, QTextEdit, QCheckBox, QFormLayout, QPushButton

from PyQt5 import QtWidgets


def bind(objectName, propertyName, type):

    def getter(self):
        return type(self.findChild(QObject, objectName).property(propertyName).toPyObject())
    
    def setter(self, value):
        self.findChild(QObject, objectName).setProperty(propertyName, QVariant(value))
    
    return property(getter, setter)

class Window(QWidget):

    def __init__(self, parent = None):
    
        super().__init__(parent)
        self.nameEdit = QLineEdit()
        self.nameEdit.setObjectName("nameEdit")
        self.addressEdit = QTextEdit()
        self.addressEdit.setObjectName("addressEdit")
        self.contactCheckBox = QCheckBox()
        self.contactCheckBox.setObjectName("contactCheckBox")
        self.button_1 = QPushButton('press me !!!')
        self.button_1.clicked.connect(self.pushButton_1_Pressed)
        
        self.button_2 = QPushButton('press me !!! second')
        self.button_2.clicked.connect(self.pushButton_2_Pressed)
        

        self.layout = QFormLayout(self)
        self.layout.addRow(self.tr("Name:"), self.nameEdit)
        self.layout.addRow(self.tr("Address:"), self.addressEdit)
        self.layout.addRow(self.tr("Receive extra information:"), self.contactCheckBox)
        
        self.layout.addWidget(self.button_1)
        self.layout.addWidget(self.button_2)
        
        self.setLayout(self.layout)
        
        self.name = bind('nameEdit', 'text', str)
        self.address = bind("addressEdit", "plainText", str)
        self.contact = bind("contactCheckBox", "checked", bool)
            
    def pushButton_1_Pressed(self):
        
        print(self.nameEdit.text())
        
        print(self.addressEdit.toPlainText())
        
        print(self.contactCheckBox.isChecked())
        
    def pushButton_2_Pressed(self):

        self.nameEdit.setText('pippo')
        
        
        self.addressEdit.clear()
        self.addressEdit.insertPlainText('papero')
        
        self.contactCheckBox.setChecked(True)
        
        print(self.nameEdit.text())
        
        print(self.addressEdit.toPlainText())
        
        print(self.contactCheckBox.isChecked())

    


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())


after you insert text into a QLineEdit or QTextEdit or check a QCheckBox widget you can print the variables defined by bind and pressing the second button you change the variable values and the text/values of the widgets at the same time (got some insight from Binding a PyQT/PySide widget to a local variable in Python.

since the inners of Python and PyQt5 are to hard to me right know, is about a dumb-proof descriprion about how bind works in the code on the three widgets.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
pippo1980
  • 2,181
  • 3
  • 14
  • 30
  • your question is unclear – eyllanesc Oct 11 '21 at 17:01
  • 1
    Are you asking how does that "bind" work? Also, your code is not valid: 1. you're trying to use the binding as instance attribute, but they are *class* attributes (look at the indentation level of those lines in the original post of the first link); 2. that code is for PyQt4, and in PyQt5 by default Qt properties are returned already converted to python objects, so remove `.toPyObject()` in the getter and change `QVariant(value)` to `value` in the setter; 3. you're *not* using those bindings at all (if you were, your program would crash due to the above issues). – musicamante Oct 11 '21 at 17:15
  • @eyllanesc, Hi its been a while... first of all why print(self.name) gives ? Actually how are properties related to the widgets – pippo1980 Oct 11 '21 at 17:16
  • @musicamante, thanks dude. I'll try to edit it for PyQt5 and see if able to manage the class variable bit, any link to 'Binding widget properties to Python variables' for PyQt5 – pippo1980 Oct 11 '21 at 17:32
  • @musicamante, sorry to bother, I can get all QLineEdit proprierties from here https://doc.qt.io/qt-5/qlineedit.html#properties (Qt documentation). How can I get them from Python ? – pippo1980 Oct 12 '21 at 16:26
  • I mean I can use for i in QLineEdit.__dict__.items() : print(i) but wich ones are properties and which are not ? – pippo1980 Oct 12 '21 at 16:46
  • 1
    @pippo1980 are you asking how to get the list of *all* properties? As far as I know, it's not possible to get it from the class, but only from one of its instances, which can be achieved through their [QMetaObject](https://doc.qt.io/qt-5/qmetaobject.html): `lineEdit = QLineEdit()` `meta = lineEdit.metaObject()` `for p in range(meta.propertyCount()):` `property = meta.property(p)`, which returns a [QMetaProperty](https://doc.qt.io/qt-5/qmetaproperty.html) for each property defined for that class. – musicamante Oct 12 '21 at 18:38
  • Thanks wasn’t able to distinguish between attributes and attributes-properties – pippo1980 Oct 12 '21 at 19:12
  • got it print(p , ' : ',property.name()) – pippo1980 Oct 13 '21 at 15:02

1 Answers1

2

The article you are referring to tries to implement the python properties using the QObjects properties.

Since it is a property it should not be declared within the class but at the method level as class attribute. On the other hand, the code must be updated since it is written for PyQt4 where the conversion between objects from python to Qt was not implicit, considering the above, the solution is:

import sys

from PyQt5.QtCore import QObject
from PyQt5.QtWidgets import (
    QApplication,
    QWidget,
    QLineEdit,
    QTextEdit,
    QCheckBox,
    QFormLayout,
    QPushButton,
)


def bind(objectName, propertyName):
    def getter(self):
        return self.findChild(QObject, objectName).property(propertyName)

    def setter(self, value):
        self.findChild(QObject, objectName).setProperty(propertyName, value)

    return property(getter, setter)


class Window(QWidget):
    name = bind("nameEdit", "text")
    address = bind("addressEdit", "plainText")
    contact = bind("contactCheckBox", "checked")

    def __init__(self, parent=None):
        super().__init__(parent)
        self.nameEdit = QLineEdit()
        self.nameEdit.setObjectName("nameEdit")
        self.addressEdit = QTextEdit()
        self.addressEdit.setObjectName("addressEdit")
        self.contactCheckBox = QCheckBox()
        self.contactCheckBox.setObjectName("contactCheckBox")
        self.button_1 = QPushButton("press me !!!")
        self.button_1.clicked.connect(self.pushButton_1_Pressed)

        self.button_2 = QPushButton("press me !!! second")
        self.button_2.clicked.connect(self.pushButton_2_Pressed)

        layout = QFormLayout(self)
        layout.addRow(self.tr("Name:"), self.nameEdit)
        layout.addRow(self.tr("Address:"), self.addressEdit)
        layout.addRow(self.tr("Receive extra information:"), self.contactCheckBox)

        layout.addWidget(self.button_1)
        layout.addWidget(self.button_2)

    def pushButton_1_Pressed(self):
        print(self.name)
        print(self.address)
        print(self.contact)

    def pushButton_2_Pressed(self):
        self.name = "pippo"
        self.address = ""
        self.address += "papero"
        self.contact = True
        print(self.address)
        print(self.contact)


if __name__ == "__main__":

    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • hi any hint about how to understand python properties and widget properties ? – pippo1980 Oct 11 '21 at 17:36
  • 2
    @pippo1980 About python properties read the link of my post and about Qt properties read the official docs: https://doc.qt.io/qt-5/properties.html – eyllanesc Oct 11 '21 at 17:37
  • sorry didnt get the link, now I see it, thanks. Is PyQt5 officially on github or Do I need to download from riverbank ? – pippo1980 Oct 11 '21 at 17:38
  • 1
    @pippo1980 PyQt is not officially on github (but there are unofficial repositories), and you should install it using pip anyway. – musicamante Oct 11 '21 at 17:40
  • okeydokey , cheers again – pippo1980 Oct 11 '21 at 17:41
  • 1
    @pippo1980 Even if it were in GH I don't think it would be useful to you since there is almost nothing written in python, most of them are .sip files. PyQt5 only exposes Qt5 without adding any magic to it. You can download the source code and check it: https://pypi.org/project/PyQt5/#files – eyllanesc Oct 11 '21 at 17:48