Мой вопрос может быть непонятным. По сути, у меня есть список, и мне нужно установить сигнал при добавлении в список или изменить размер для запуска функции. Ниже приведен простой пример того, что я хочу. Это возможно в 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[:] = []  
0
Arc Zezo 17 Июн 2020 в 20:16

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

Обратите внимание, что в вашем примере сигнал не будет испускаться, потому что вы используете метод получения только для получения существующего объекта res, затем вы вызываете метод добавления для этого списка; сеттер никогда не будет вызываться таким образом.

0
musicamante 18 Июн 2020 в 13:57