Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PySide implicitely create object members from class members for Signals?

Tags:

signals

pyside

On the PySide signals and slots page it says: "Signals are runtime objects owned by instances, they are not class attributes". Apparently the QObject constructor looks in the class attributes for Signals and copies them to the object instance. This is confirmed by my test program.

from PySide import QtCore

class Klass(QtCore.QObject):
    lst = []
    sig = QtCore.Signal(str)

def main():
    obj1 = Klass()
    obj2 = Klass()

    print "id: obj1.lst  = {}, obj1.sig  = {}".format(id(obj1.lst),  id(obj1.sig))
    print "id: obj2.lst  = {}, obj2.sig  = {}".format(id(obj2.lst),  id(obj2.sig))
    print "id: klass.lst = {}, klass.sig = {}".format(id(Klass.lst), id(Klass.sig))

if __name__ == '__main__':
    main()

In my output you can see that there are now three signal objects whereas the id of lst-member is the same for both objects and the class.

id: obj1.lst  = 4317739344, obj1.sig  = 4297560376
id: obj2.lst  = 4317739344, obj2.sig  = 4297560400
id: klass.lst = 4317739344, klass.sig = 4317851072

Implicitly creating the object attributes is just confusing and therefore bad style (IMHO). Maybe they do have good reasons for this but I don't see them. So my question is: why did they choose this solution instead of just creating the signal as a regular attribute in the constructor?

like image 228
titusjan Avatar asked Feb 22 '13 13:02

titusjan


People also ask

What is signal and slot in PYQT?

A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal.

What is a signal in PYQT?

Signals are notifications emitted by widgets when something happens. That something can be any number of things, from pressing a button, to the text of an input box changing, to the text of the window changing. Many signals are initiated by user action, but this is not a rule.


1 Answers

They are not copies. If you check the type of those, you'll see that the class attribute is PySide.QtCore.Signal and the instance attribute is PySide.QtCore.SignalInstance.

print "type(obj1.sig): {}".format(type(obj1.sig))
print "type(obj2.sig): {}".format(type(obj2.sig))
print "type(Klass.sig): {}".format(type(Klass.sig))

# type(obj1.sig): <type 'PySide.QtCore.SignalInstance'>
# type(obj2.sig): <type 'PySide.QtCore.SignalInstance'>
# type(Klass.sig): <type 'PySide.QtCore.Signal'>

This is necessary because of the way Qt defines signals. Qt uses Meta-Object System to register signals/slots. In order to make this work, PySide does some 'magic' behind the curtain to register your custom class-attribute signal with Meta-Object System and return you a usable signal (SignalInstance) with the same name as instance attribute.

Original Signal is still there, but rather overridden with the instance attribute:

print "obj1.sig -> type: {}, id: {}".format(type(obj1.sig), id(obj1.sig))
print "obj1.__class__.sig -> type: {}, id: {}".format(type(obj1.__class__.sig), id(obj1.__class__.sig))
print "Klass.sig -> type: {}, id: {}".format(type(Klass.sig), id(Klass.sig))

# obj1.sig -> type: <type 'PySide.QtCore.SignalInstance'>, id: 40629904
# obj1.__class__.sig -> type: <type 'PySide.QtCore.Signal'>, id: 41556352
# Klass.sig -> type: <type 'PySide.QtCore.Signal'>, id: 41556352
like image 150
Avaris Avatar answered Jan 01 '23 10:01

Avaris