【问题标题】:Pyqt5 signal and slot upon modifying a list修改列表时的 Pyqt5 信号和槽
【发布时间】:2020-10-07 14:37:09
【问题描述】:

我的问题可能不清楚。基本上,我有一个列表,当附加到列表或更改大小以运行函数时,我需要安装一个信号。下面是我想要的一个简单示例。 它在 PyQt5 中可行还是没有这样的事情?

from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot

class MyList(QObject):

    # Signal emitted when the list is resized, int:newsize
    resized = pyqtSignal(list)

    def __init__(self):
        QObject.__init__(self)

        # "Hide" the values and expose them via properties
        self._list = [1,2]

    @property
    def res(self):
        return self._list

    @res.setter
    def res(self, new_list):
        self._list.append(new_list)
        self.resized.emit(new_list)


# A slot for the "resized" signal, accepting the radius
@pyqtSlot(list)
def on_resized(r):
    print('resized', r)


c = MyList()

# 
c.resized.connect(on_resized)

# 
c.res.append(20) 

# delete all
c.res[:] = []  

【问题讨论】:

  • 您是否在问如何创建自定义信号以及如何发出它们?
  • 是的。我想要的信号是在列表更改大小时发出的。然后运行连接到该信号的函数。希望你能帮忙

标签: python pyqt pyqt5


【解决方案1】:

您可以创建list 的子类并使用带有自定义信号的简单 QObject,然后覆盖所有可能更改列表大小的方法,以便您可以为每个方法发出信号。

class ListProxy(QtCore.QObject):
    resized = QtCore.pyqtSignal(list)

class SignalList(list):
    def __init__(self, *args):
        super().__init__(*args)
        self._proxy = ListProxy()
        self.resized = self._proxy.resized

    def append(self, item):
        super().append(item)
        self.resized.emit(self)

    def extend(self, iterable):
        super().extend(iterable)
        self.resized.emit(self)

    def pop(self, *args):
        item = super().pop(*args)
        self.resized.emit(self)
        return item

    # this is required for slicing -> myList[:] = []
    # you might want to check if the length of the list is actually changed
    # before emitting the signal
    def __setitem__(self, *args, **kwargs):
        super().__setitem__(*args, **kwargs)
        self.resized.emit(self)

    def __delitem__(self, *args, **kwargs):
        super().__delitem__(*args, **kwargs)
        self.resized.emit(self)

    # this is required for concatenation -> myList += iterable
    def __iadd__(self, *args, **kwargs):
        super().__iadd__(*args, **kwargs)
        self.resized.emit(self)
        return self

请注意,在您的示例中,不会发出信号,因为您仅使用 getter 来获取现有的 res 对象,然后调用该列表的 append 方法;永远不会以这种方式调用 setter。

【讨论】:

  • 非常感谢。它运作良好。只有一个错误,我用多处理 manager.list() 替换了“ListProxy()”。它给了我这个错误。 AttributeError:“ListProxy”对象没有“调整大小”的属性。你能告诉我如何解决它。我添加的代码行是“以 Manager() 作为经理:self._proxy = manager.list() self.resized = self._proxy.resized”
  • 答案正是在您的问题中:您将 ListProxy 替换为其他东西,这完全不同。我真的不明白你为什么这样做,这完全NO有意义。仔细阅读我的回答,试着理解代码的作用,不要随意即兴发挥。
  • 谢谢,抱歉打扰。我正在尝试做的实际代码是处理器之间的共享列表(使用 manager.list())。当我发布这个问题时,我想让它变得简单。所以,我使用了简单的列表。再次感谢您的宝贵时间
  • 使用不同的类(这可能会改变逻辑,特别是如果你想使用线程)不会简化,缺少信息。如果你想使用manager.list,那么你应该从它继承SignalList,而不是像我的例子中那样简单的列表;当然,您不应该替换 ListProxy,它不是一个列表,而是一个用于发送信号来自列表对象的 QObject。
  • 非常感谢。是的,我试图从“Manager.list”创建一个子类,但我遇到了一个错误。那我就放弃了。我将尝试以不同的方式解决问题。谢谢你的帮助:)
猜你喜欢
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 2019-05-06
  • 2019-04-20
  • 2016-07-17
  • 2013-10-08
  • 1970-01-01
  • 2016-07-27
相关资源
最近更新 更多