使用间隔计时器进行迭代

Iterate with an interval timer

我正在尝试创建一个函数,它接受项目列表并以指定的时间间隔(使用 Qt 框架中的 QTimer)迭代它们,而不中断程序流的其余部分。

我已经设法使用以下使用内部函数的代码来实现这一点,但我很好奇这是否可以在不使用 self.index 实例变量的情况下以更优雅的方式完成。理想情况下,此计数器应封装在 iterate_with_interval 方法中,但我找不到不使用 global.

来递增它的方法

我想这可以通过专门的 class 来完成,但我想知道如果没有它是否可以完成。

from PySide6.QtCore import QTimer
from PySide6.QtWidgets import QWidget, QApplication


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.index = 0
        self.iterate_with_interval(['a', 'b', 'c', 'd', 'e'], 200)
        print('Execution continues')

    def iterate_with_interval(self, items, interval):
        timer = QTimer()
        timer.setInterval(interval)

        def iterate(items, timer):
            if self.index < len(items):
                print(items[self.index])
                self.index += 1
            else:
                timer.stop()

        timer.timeout.connect(lambda: iterate(items, timer))
        timer.start()


if __name__ == '__main__':
    app = QApplication()
    window = MainWindow()
    window.show()
    app.exec()

你总是需要一个获取列表值的中间函数,所以最优雅的解决方案是创建一个 class 通过迭代器处理逻辑。

from PySide6.QtCore import QTimer, Signal
from PySide6.QtWidgets import QWidget, QApplication


class TimerIterator(QTimer):
    value_changed = Signal(object)

    def __init__(self, values=None, parent=None):
        super().__init__(parent)
        self._values = []
        self.timeout.connect(self.handle_timeout)
        
        self.values = values or []

    @property
    def values(self):
        return self._values

    @values.setter
    def values(self, values):
        self._values = values
        self.setProperty("iterator", iter(self.values))

    def handle_timeout(self):
        try:
            value = next(self.property("iterator"))
        except StopIteration:
            self.stop()
        else:
            self.value_changed.emit(value)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.timer_iterator = TimerIterator()
        self.timer_iterator.values = ["a", "b", "c", "d", "e"]
        self.timer_iterator.setInterval(200)
        self.timer_iterator.value_changed.connect(print)
        self.timer_iterator.start()


if __name__ == "__main__":
    app = QApplication()
    window = MainWindow()
    window.show()
    app.exec()