PySide * любой * вызов метода - СИГНАЛЫ и СЛОТЫ - PullRequest
0 голосов
/ 24 декабря 2018

Я пытаюсь создать простой универсальный вызов метода для моей библиотеки 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 с аргументами:

    @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))

Я вижу, что этот подход не работает, и аргументы передаются неправильно.Что я должен сделать, чтобы исправить?

1 Ответ

0 голосов
/ 24 декабря 2018

Сигналы должны быть определены не как члены класса, а как атрибуты класса.С другой стороны, вы должны указать подпись, и, наконец, словари не поддерживают, поэтому вы должны преобразовать *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())
...