PyQt如何发挥其魔力?特别是,它如何允许我们在Python中实现插槽?

时间:2012-04-09 07:57:12

标签: pyqt pyqt4 implementation internals

当我了解PyQt时,有三件事让我惊讶。这是关于第二个问题的问题,但是如果其他任何人都好奇的话,请让我为这三个人命名:

  1. 首先,我们被允许在Python中继承C ++类(可以这么说),覆盖Python中的C ++方法 - 并将我们的类传递回Qt框架,这将称他们为C ++!
  2. 第二,插槽。在核心Qt中,它们是C ++类的方法。但在PyQt中,我们可以轻松地将Python方法用作插槽,并且它们将被调用。 (它们似乎不适用于Qt“内省”系统,尽管 *)
  3. 第三,信号。在Qt中,它们是静态生成的C ++代码 - 那么PyQt如何聪明地允许我们在Python中创建它们(a)和(b)基本上,在运行中?
  4. 我想我理解(1)(对于每个使用virtual方法的类,SIP生成一个继承它的子类,保存对Python对象的引用,以便为每个重写方法生成的代码首先检查一个Python方法存在),(3)不应该太难理解知道(2)。

    this article开始,要有(2)我们必须为Python类实现qt_metacall()方法,并通过为我们提供相应的QMetaObject将其链接到Qt“metasystem” PyQt类。

    我会感激任何关于它是如何完成的提示,无论是在PyQt还是PySide,或者它是如何使用Boost :: Python为PySide做的。

    特别是,我想知道PyQt4.QtCore.SLOT()用作相应Python方法的签名字符串。

    PS。正如在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来列出信号。并且 - 不,类(PyQt4.QtCore.pyqtSignal()个)的PyQt信号也不会列出。)

1 个答案:

答案 0 :(得分:0)

您可以在现代版本的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中不起作用。