【问题标题】:How does PyQt do its magic? In particular, how it allows us to implement slots in Python?PyQt 如何发挥它的魔力?特别是,它如何让我们在 Python 中实现插槽?
【发布时间】:2012-04-21 15:56:30
【问题描述】:

当我了解 PyQt 时,有三件事让我感到好奇。这是关于第二个的问题,但让我说出所有三个以防万一其他人好奇:

  1. 首先,我们可以继承 Python 中的 C++ 类(可以这么说),覆盖 Python 中的 C++ 方法 -- 并将我们的类传回 Qt 框架,它将调用它们,因为它们是 C++ !
  2. 其次,插槽。在核心 Qt 中,它们是 C++ 类的方法。但是在 PyQt 中,我们可以轻松地将 Python 方法用作插槽,它们会被调用。 (不过,对于 Qt“自省”系统,它们似乎不可见*)
  3. 第三,信号。在 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


    【解决方案1】:

    您可以在现代版本的 PyQt 中使用装饰器。例如:

    @QtCore.pyqtSlot()
    @QtCore.pyqtSlot('bool')  
    def coolSlotActions(self, b=True):
       """ my slot called, with two different signatures """
       pass # do something cool!
    

    the PyQt 4.9.4 docs 中的更多信息。据我所知,这在 pyside 中不起作用。

    【讨论】:

      猜你喜欢
      • 2016-12-02
      • 2015-10-02
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 2020-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多