【发布时间】:2012-04-21 15:56:30
【问题描述】:
当我了解 PyQt 时,有三件事让我感到好奇。这是关于第二个的问题,但让我说出所有三个以防万一其他人好奇:
- 首先,我们可以继承 Python 中的 C++ 类(可以这么说),覆盖 Python 中的 C++ 方法 -- 并将我们的类传回 Qt 框架,它将调用它们,因为它们是 C++ !
- 其次,插槽。在核心 Qt 中,它们是 C++ 类的方法。但是在 PyQt 中,我们可以轻松地将 Python 方法用作插槽,它们会被调用。 (不过,对于 Qt“自省”系统,它们似乎不可见*))
- 第三,信号。在 Qt 中,它们是静态生成的 C++ 代码——那么 PyQt 是如何聪明地允许我们在 Python 中创建它们(a)和(b)基本上是动态的?
我想我理解 (1) (对于每个具有virtual 方法的类,SIP 生成一个继承它的子类,持有对 Python 对象的引用,以便为每个被覆盖的方法生成的代码首先检查 Python方法存在),并且(3)不应该太难理解知道(2)。
正如this article 所遵循的那样,要获得 (2),我们必须为我们的 Python 类实现 qt_metacall() 方法,并通过为我们的 PyQt 类提供相应的 QMetaObject 将其链接到 Qt“元系统”。
我将不胜感激任何关于它是如何完成的提示,无论是在 PyQt 或 PySide 中,还是关于它如何在 PySide 之前使用 Boost::Python 完成的。
我特别想知道 PyQt4.QtCore.SLOT() 使用什么作为相应 Python 方法的签名字符串。
附言。正如related post 中所说,“这个问题is already asked 在这个论坛上,但我不明白这个概念”。
*) 下面的代码列出了 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()
(使用 1 而不是 2 来列出信号。而且——不,一个类的 PyQt 信号(PyQt4.QtCore.pyqtSignal() 个)也不会被列出。)
【问题讨论】:
标签: pyqt pyqt4 implementation internals