当我了解 PyQt 时,有三件事让我感到好奇。这是关于第二个的问题,但让我说出所有三个以防万一其他人好奇:
- 首先,我们可以在 Python 中继承 C++ 类(可以这么说),覆盖 Python 中的 C++ 方法——并将我们的类传递回 Qt 框架,Qt 框架将调用它们,就像它们是 C++ 一样!
- 第二,插槽。在核心 Qt 中,它们是 C++ 类的方法。但是在 PyQt 中,我们可以轻松地将 Python 方法用作插槽,它们会被调用。(它们似乎对 Qt“内省”系统不可见,尽管*))
- 第三,信号。在 Qt 中,它们是静态生成的 C++ 代码——那么 PyQt 是如何聪明地允许我们在 Python 中创建它们(a)和(b)基本上是动态的?
我想我理解(1)(对于每个具有virtual
方法的类,SIP 生成一个继承它的子类,持有对 Python 对象的引用,以便为每个被覆盖的方法生成的代码首先检查是否存在 Python 方法),以及( 3)知道(2)不应该太难理解。
正如本文所得出的那样,要拥有 (2),我们必须为我们的 Python 类实现该qt_metacall()
方法,并通过为我们的 PyQt 类提供相应的 QMetaObject 来将其链接到 Qt“元系统”。
我将不胜感激有关它是如何完成的任何提示,无论是在 PyQt 或 PySide 中,还是在之前使用 Boost::Python 为 PySide 完成的。
特别是,我想知道 PyQt4.QtCore.SLOT() 使用什么作为相应 Python 方法的签名字符串。
PS。正如在相关帖子中所说,“这个问题已经在这个论坛中提出,但我不明白这个概念”。
*) 下面的代码列出了 Qt 对象的插槽;不出所料,Python 对象方法不会显示在此列表中,即使它们是 connect()-ed。(有没有办法列出当前作为插槽工作的 Python 方法?)
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()
PyQt4.QtCore.pyqtSignal()
(使用 1 而不是 2 来列出信号。而且 - 不,也不会列出类( one )的 PyQt 信号。)