PySide *any* 方法调用 - SIGNALs 和 SLOTs

PySide *any* method call - SIGNALs and SLOTs

我正在尝试为我的 PySide GUI 库创建简单、通用的方法调用:

class GUI(QApplication):
    def __init__(self, *args, **kwargs):
        super(GUI, self).__init__()
        self.gui_signal = Signal()
        self.gui_signal.connect(self.method_call)

插槽获取对象、方法并调用 object.method with args:

    @Slot()
    def method_call(self, obj, method_name, *args, **kwargs):
        method = getattr(obj, method_name)
        if method:
            return method(*args, **kwargs)
        else:
            return None

这应该发出那个棘手的插槽:

    def anymethod(self, obj, method_name, *args, **kwargs):
        self.gui_signal.emit(obj, method_name, *args, **kwargs)

这是另一个工作线程,例如更新进度条

class MyApp(object):
    ...

    def update_progress(self):
        perc = (self.done * 100) / self.total
        self.gui.anymethod(self.progressBar, 'setValue', int(perc))

我发现这种方法行不通,而且 args 的传递方式有误。我应该怎么做才能解决?

信号不应定义为 class 的成员,而应定义为 class 的属性。另一方面你必须注明签名,最后,字典不支持所以你必须将*args**kwargs转换为元组。

from PySide import QtCore, QtGui

class GUI(QtGui.QApplication):
    gui_signal = QtCore.Signal(object, str, tuple)

    def __init__(self, *args, **kwargs):
        super(GUI, self).__init__([])
        self.gui_signal.connect(self.method_call)

    @QtCore.Slot(object, str, tuple)
    def method_call(self, obj, method_name, data):
        if hasattr(obj, method_name):
            method = getattr(obj, method_name)
            args, kwargs = data
            if hasattr(method, '__call__'):
                method(*args, **kwargs)

    def anymethod(self, obj, method_name, *args, **kwargs):
        self.gui_signal.emit(obj, method_name, (args, kwargs))

class MyApp(object):
    def __init__(self):
        self.gui = GUI()

        self.progressBar = QtGui.QProgressBar(maximum=100)
        self.progressBar.show()

        self.total = 200
        self.done = 100
        QtCore.QTimer.singleShot(300, self.update_progress)

    def update_progress(self):
        perc = (self.done * 100) / self.total
        self.gui.anymethod(self.progressBar, 'setValue', int(perc))

    def run(self):
        return self.gui.exec_()

if __name__ == '__main__':
    import sys
    app = MyApp()
    sys.exit(app.run())