When I learned about PyQt, there were three things to make me wonder. This is the question about the second one, but let me name all the three just in case if anyone else would be curious:
- first, we are allowed to subclass the C++ classes in Python (so to say), override the C++ methods in Python -- and to pass our classes back to the Qt framework, which will call them as they were C++ !
- second, the slots. in core Qt they are methods of a C++ class. but in PyQt, we can easily use Python methods as slots, and they will get called. (They do not seem to be visible for the Qt "introspection" system, though*))
- third, the signals. in Qt, they are statically generated C++ code -- so how is PyQt so smart to allow us to create them (a) in Python and (b) basically, on the fly ?
I think I understand (1) ( for every class with virtual
methods, SIP generates a subclass that inherits it, holding a reference to the Python object, so that the generated code for every overridden method first checks if a Python method exists ), and (3) shouldn't be too hard to understand knowing (2).
As it follows from this article, to have (2) we have to implement the qt_metacall()
method for our Python class and to link it to the Qt "metasystem" by providing a corresponding QMetaObject for our PyQt class.
I'll be grateful for any hints on how it's done, either in PyQt or PySide, or on how it was done for PySide earlier with Boost::Python.
In particular, I wonder what PyQt4.QtCore.SLOT() uses as a signature string for a corresponding Python method.
PS. As was said in a related post, "this question is already asked in this forum but I don't understand the concept".
*) The code below lists the slots for a Qt object; not as much unexpected, Python object methods do not show in this list, even if they are connect()-ed. ( Is there a way to make a list of Python methods which are currently working as slots? )
def print_object_slots( qt_object, this_class_only = False ):
# there was a method called signalNames(), and, I suspect, slotNames(),
# but it was removed in Qt 4 [ http://www.qtforum.org/article/33122/method-qmetaobject-signalnames-removed-in-qt4.html#post106693 ]
mo = qt_object.metaObject()
nmethods = mo.methodCount()
first_method_offset = 0
if this_class_only :
first_method_offset = mo.methodOffset() # assert != -1
# or use PyQt.QtCore.QMetaMethod.Slot
type_slot = 2 # [ http://doc.qt.nokia.com/4.6/qmetamethod.html#MethodType-enum ]
# list the slots
for i in xrange( first_method_offset, nmethods ):
meth = mo.method(i)
if meth.methodType() == type_slot :
print meth.signature()
( Use 1 instead of 2 to list signals. And -- no, PyQt signals of a class ( PyQt4.QtCore.pyqtSignal()
ones ) won't be listed either. )