1

PySide 声称Signals can be defined using the QtCore.Signal() class. Python types and C types can be passed as parameters to it. If you need to overload it just pass the types as tuples or lists. 从 PySide 中的 PySide Doc Si​​gnals and Slots 中,他们展示了一种同时创建多个信号的方法。那条线是:

# create two new signals on the fly: one will handle
# int type, the other will handle strings
speak = QtCore.Signal((int,), (str,))

我走了一点,创造了这样的东西(用于学习目的):

speak = QtCore.Signal((int,), (str,), (tuple,), (list,), (A,), (B,), (Exception,), (unicode,), (float,))

A并且B是我创建的两个不同的虚拟新样式类。然后我通过打印它们来调查实际创建了多少信号:

print someone.speak
print someone.speak[int]
print someone.speak[str]
print someone.speak[tuple]
print someone.speak[list]
print someone.speak[A]
print someone.speak[B]
print someone.speak[Exception]
print someone.speak[unicode]
print someone.speak[float]

我得到了这些:

<PySide.QtCore.SignalInstance object at 0x02179BA0>
<PySide.QtCore.SignalInstance object at 0x02179BA0>
<PySide.QtCore.SignalInstance object at 0x02179BB0>
<PySide.QtCore.SignalInstance object at 0x02179BC0>
<PySide.QtCore.SignalInstance object at 0x02179BC0>
<PySide.QtCore.SignalInstance object at 0x02179BC0>
<PySide.QtCore.SignalInstance object at 0x02179BC0>
<PySide.QtCore.SignalInstance object at 0x02179BC0>
<PySide.QtCore.SignalInstance object at 0x02179BB0>
<PySide.QtCore.SignalInstance object at 0x02179C00>

Obersevation: tuple, list,Exception和我的习惯AB得到相同的信号。我知道元组和列表有点笼统,被 PySide 用来重载东西。但为什么我的AB也得到相同的信号?看起来只有那些真正原始的类型,如int,float并且str在 Python 中获得新信号。

任何人都可以解释这种奇怪的行为吗?

提前非常感谢!

[更新]

当我在一个真正的 PySide 项目中遇到问题时,我做了上述探索。我将真实版本简化为:

#!/usr/bin/env python
import sys
from PySide import QtCore

class A(object):
    def __init__(self, msg):
        self.msg = msg

class B(object):
    def __init__(self, msg):
        self.msg = msg

@QtCore.Slot(A)
def sayA(a):
    print 'From sayA:', a.msg

@QtCore.Slot(B)
def sayB(b):
    print 'From sayB:', b.msg

class Communicate(QtCore.QObject):
    speak = QtCore.Signal((A,), (B,))

someone = Communicate()

someone.speak[A].connect(sayA)
someone.speak[B].connect(sayB)

someone.speak[A].emit(A('A is good'))
someone.speak[B].emit(B('B is bad'))

它将打印出:

From sayA: A is good
From sayB: A is good
From sayA: B is bad
From sayB: B is bad

我预计A is good只能从 sayA 打印。

4

2 回答 2

1

请参阅与您的问题相关的问题的答案:

是的,可以使用 python 对象定义信号,您可以使用:

signal_node_selected = QtCore.Signal(对象)

我假设传递任何自定义 Python 类都被视为传递object. 没有办法让信号区分它们。

于 2013-07-30T10:53:26.403 回答
0

感谢您的研究!我遇到了同样的问题,并通过链接信号和使用备用名称来承载不同的数据来解决它:

class King(QtGui.QWidget):
    summon = QtCore.Signal(str)
    summon_knights = QtCore.Signal(object)

    def __init__(self, parent=None):
        super(King, self).__init__(parent=parent)

        summon.connect(lambda x: self.summon_knights.emit(self.get_available_knights()))

    def get_available_knights(self):
        return ["Lancelot", "Galahad"]

lambda 是为了处理或忽略调用信号携带的 str 。

这是我不太优雅的草稿工作,以向自己证明它的行为不像我想要的那样。睡眠是为了强制结果按时间顺序排列,因为异步信号/插槽行为会导致它变得非常混乱(这有利于速度,但难以解释)。

from PySide import QtCore
from PySide import QtGui
import sys
from collections import OrderedDict
from time import sleep

class Analyst(QtCore.QObject):

    finished = QtCore.Signal((object,), (list,))

    def __init__(self, parent=None):
        super(Analyst, self).__init__(parent=parent)

        self.number = 10000.0

    def analyze(self):
        print "Analyst working!"
        result = OrderedDict()
        result["a"] = self.number / 100.0
        result["b"] = self.number / 200.0

        sleep(1)

        report = ['Analysis Report',
                  ' a: {0}'.format(result["a"]),
                  ' b: {0}'.format(result["b"])
                  ]

        print "Analyst done!"

        self.finished[object].emit(result)
        sleep(1)
        self.finished[list].emit(report)

class Manager(QtCore.QObject):

    announceStartWork = QtCore.Signal()
    allDone = QtCore.Signal()

    def __init__(self, parent=None):
        super(Manager, self).__init__(parent=parent)

        self.analyst = Analyst(self)
        self.analyst.finished[object].connect(self.post_process)
        self.analyst.finished[list].connect(self.report_result)
        self.announceStartWork.connect(self.analyst.analyze)
        self.reportsDone = False
        self.resultsDone = False
        self.allDone.connect(self.exitWhenReady)

    def directAnalyst(self):
        print "Telling analyst to start"
        self.announceStartWork.emit()

    def post_process(self, results):

        print "Results type (expecting OrderedDict): {0}".format(type(results))

        if issubclass(type(results), dict):
            summation = 0
            for value in results.values():
                summation += value

            print "Sum of Results: {0}".format(summation)
            self.resultsDone = True
            self.allDone.emit()
        else:
            print "*** WRONG TYPE! DICT slot got the LIST!"


    def report_result(self, report):

        print "Report type (expecting list): {0}".format(type(report))

        if issubclass(type(report), list):
            report_str = '\n'.join(report)
            print "Report of original result: \n{0}".format(report_str)

            self.reportsDone = True
            self.allDone.emit()
        else:
            print "*** WRONG TYPE! LIST slot got the DICT!"


    def exitWhenReady(self):
        tasksCompleted = [self.reportsDone, self.resultsDone]
        if all(tasksCompleted):
            print "All tasks completed"
            app.exit()
        else:
            print "Not all tasks completed yet"


if __name__ == "__main__":

    app = QtCore.QCoreApplication([])
    manager = Manager()
    manager.directAnalyst()
    sys.exit(app.exec_())

这是输出:

Telling analyst to start
Analyst working!
Analyst done!
Results type (expecting OrderedDict): <class 'collections.OrderedDict'>
Sum of Results: 150.0
Not all tasks completed yet
Report type (expecting list): <class 'collections.OrderedDict'>
*** WRONG TYPE! LIST slot got the DICT!
Results type (expecting OrderedDict): <type 'list'>
*** WRONG TYPE! DICT slot got the LIST!
Report type (expecting list): <type 'list'>
Report of original result: 
Analysis Report
 a: 100.0
 b: 50.0
All tasks completed

好的,所以我在上面的 Manager、Analyst 示例上实现了我自己的“修复”,并得出以下结论:

from PySide import QtCore
from PySide import QtGui
import sys
from collections import OrderedDict
from time import sleep

class Analyst(QtCore.QObject):

    finished_result = QtCore.Signal(object)
    finished_report = QtCore.Signal(object)
    _finished = QtCore.Signal(object)

    def __init__(self, parent=None):
        super(Analyst, self).__init__(parent=parent)

        self.number = 10000.0
        self._finished.connect(self._make_signal)

    def analyze(self):
        print "Analyst working!"
        result = OrderedDict()
        result["a"] = self.number / 100.0
        result["b"] = self.number / 200.0

        sleep(1)

        report = ['Analysis Report',
                  ' a: {0}'.format(result["a"]),
                  ' b: {0}'.format(result["b"])
                  ]

        print "Analyst done!"

        self._finished.emit(("result", result))
        sleep(1)
        self._finished.emit(("report", report))

    def _make_signal(self, data):

        if data[0] == "result":
            self.finished_result.emit(data[1])
        elif data[0] == "report":
            self.finished_report.emit(data[1])


class Manager(QtCore.QObject):

    announceStartWork = QtCore.Signal()
    allDone = QtCore.Signal()

    def __init__(self, parent=None):
        super(Manager, self).__init__(parent=parent)

        self.analyst = Analyst(self)
        self.analyst.finished_result.connect(self.post_process)
        self.analyst.finished_report.connect(self.report_result)
        self.announceStartWork.connect(self.analyst.analyze)
        self.reportsDone = False
        self.resultsDone = False
        self.allDone.connect(self.exitWhenReady)

    def directAnalyst(self):
        print "Telling analyst to start"
        self.announceStartWork.emit()

    def post_process(self, results):

        print "Results type (expecting OrderedDict): {0}".format(type(results))

        if issubclass(type(results), dict):
            summation = 0
            for value in results.values():
                summation += value

            print "Sum of Results: {0}".format(summation)
            self.resultsDone = True
            self.allDone.emit()
        else:
            print "*** WRONG TYPE! DICT slot got the LIST!"

    def report_result(self, report):

        print "Report type (expecting list): {0}".format(type(report))

        if issubclass(type(report), list):
            report_str = '\n'.join(report)
            print "Report of original result: \n{0}".format(report_str)

            self.reportsDone = True
            self.allDone.emit()
        else:
            print "*** WRONG TYPE! LIST slot got the DICT!"


    def exitWhenReady(self):
        tasksCompleted = [self.reportsDone, self.resultsDone]
        if all(tasksCompleted):
            print "All tasks completed"
            app.exit()
        else:
            print "Not all tasks completed yet"


if __name__ == "__main__":

    app = QtCore.QCoreApplication([])
    manager = Manager()
    manager.directAnalyst()
    sys.exit(app.exec_())

具有以下输出:

Telling analyst to start
Analyst working!
Analyst done!
Results type (expecting OrderedDict): <class 'collections.OrderedDict'>
Sum of Results: 150.0
Not all tasks completed yet
Report type (expecting list): <type 'list'>
Report of original result: 
Analysis Report
 a: 100.0
 b: 50.0
All tasks completed
于 2014-02-10T21:14:01.127 回答