如何更改 Qthread 内 Qtimer 的时间间隔?

2024-03-14

我希望能够更改 QThread 内 QTimer 的间隔时间。这是我的代码。

import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QObject, QTimer, QThread


class Worker(QObject):
    def __init__(self):
        QObject.__init__(self)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.work)

    def start(self):
        self.timer.start(1000)

    def work(self):
        print("Hello World...")

    def set_interval(self, interval):
        self.timer.setInterval(interval)


def main():
    # Set up main window
    app = QApplication(sys.argv)
    win = QMainWindow()
    win.setFixedSize(200, 100)
    spinbox_interval = QtWidgets.QSpinBox(win)
    spinbox_interval.setMaximum(5000)
    spinbox_interval.setSingleStep(500)
    spinbox_interval.setValue(1000)

    worker = Worker()
    thread = QThread()
    worker.moveToThread(thread)
    thread.started.connect(worker.start)
    thread.start()

    def change_interval():
        value = spinbox_interval.value()
        worker.set_interval(value)

    spinbox_interval.valueChanged.connect(change_interval)

    win.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

如果我在启动计时器后调用worker.setInterval(),超时信号将不再发出信号。有人可以向我解释我做错了什么吗?


要了解问题,您必须在控制台/CMD 中运行以获取错误消息,从而了解原因,如果这样做,您会收到以下错误消息:

QObject::killTimer: Timers cannot be stopped from another thread
QObject::startTimer: Timers cannot be started from another thread

要理解此错误消息,您必须了解:

  • QObject 不是线程安全的,因此不能从另一个线程修改它们,
  • QObject 的子对象与父对象位于同一线程中。

因此,作为 Worker 子级的计时器作为其父级存在于辅助线程中,因此您无法从另一个线程修改它。本例中是在辅助线程中发送修改信息,为此有以下几种选择:

  • QMetaObject.invokeMethod()使用 pyqtSlot:

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox
    from PyQt5.QtCore import pyqtSlot, QMetaObject, QObject, Qt, QTimer, QThread, Q_ARG
    
    
    class Worker(QObject):
        def __init__(self):
            QObject.__init__(self)
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.work)
    
        def start(self):
            self.timer.start(1000)
    
        def work(self):
            print("Hello World...")
    
        @pyqtSlot(int)
        def set_interval(self, interval):
            self.timer.setInterval(interval)
    
    
    def main():
        # Set up main window
        app = QApplication(sys.argv)
        win = QMainWindow()
        win.setFixedSize(200, 100)
        spinbox_interval = QSpinBox(win)
        spinbox_interval.setMaximum(5000)
        spinbox_interval.setSingleStep(500)
        spinbox_interval.setValue(1000)
    
        worker = Worker()
        thread = QThread()
        worker.moveToThread(thread)
        thread.started.connect(worker.start)
        thread.start()
    
        def change_interval():
            value = spinbox_interval.value()
            QMetaObject.invokeMethod(
                worker, "set_interval", Qt.QueuedConnection, Q_ARG(int, value)
            )
    
        spinbox_interval.valueChanged.connect(change_interval)
    
        win.show()
        ret = app.exec_()
    
        QMetaObject.invokeMethod(worker.timer, "stop")
        thread.quit()
        thread.wait()
        sys.exit(ret)
    
    
    if __name__ == "__main__":
        main()
    
  • 带槽的自定义信号:

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox
    from PyQt5.QtCore import pyqtSignal, pyqtSlot, QMetaObject, QObject, Qt, QTimer, QThread
    
    
    class Worker(QObject):
        updateInterval = pyqtSignal(int)
    
        def __init__(self):
            QObject.__init__(self)
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.work)
    
            self.updateInterval.connect(self.set_interval)
    
        def start(self):
            self.timer.start(1000)
    
        def work(self):
            print("Hello World...")
    
        @pyqtSlot(int)
        def set_interval(self, interval):
            self.timer.setInterval(interval)
    
    
    def main():
        # Set up main window
        app = QApplication(sys.argv)
        win = QMainWindow()
        win.setFixedSize(200, 100)
        spinbox_interval = QSpinBox(win)
        spinbox_interval.setMaximum(5000)
        spinbox_interval.setSingleStep(500)
        spinbox_interval.setValue(1000)
    
        worker = Worker()
        thread = QThread()
        worker.moveToThread(thread)
        thread.started.connect(worker.start)
        thread.start()
    
        def change_interval():
            value = spinbox_interval.value()
            worker.updateInterval.emit(value)
    
        spinbox_interval.valueChanged.connect(change_interval)
    
        win.show()
        ret = app.exec_()
    
        QMetaObject.invokeMethod(worker.timer, "stop")
        thread.quit()
        thread.wait()
        sys.exit(ret)
    
    
    if __name__ == "__main__":
        main()
    
  • 自定义 QEvent:

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox
    from PyQt5.QtCore import QEvent, QMetaObject, QObject, Qt, QTimer, QThread
    
    
    class IntervalEvent(QEvent):
        def __init__(self, interval):
            QEvent.__init__(self, QEvent.User + 1000)
            self._interval = interval
    
        @property
        def interval(self):
            return self._interval
    
    
    class Worker(QObject):
        def __init__(self):
            QObject.__init__(self)
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.work)
    
        def start(self):
            self.timer.start(1000)
    
        def work(self):
            print("Hello World...")
    
        def set_interval(self, interval):
            self.timer.setInterval(interval)
    
        def event(self, e):
            if isinstance(e, IntervalEvent):
                self.set_interval(e.interval)
            return Worker.event(self, e)
    
    
    def main():
        # Set up main window
        app = QApplication(sys.argv)
        win = QMainWindow()
        win.setFixedSize(200, 100)
        spinbox_interval = QSpinBox(win)
        spinbox_interval.setMaximum(5000)
        spinbox_interval.setSingleStep(500)
        spinbox_interval.setValue(1000)
    
        worker = Worker()
        thread = QThread()
        worker.moveToThread(thread)
        thread.started.connect(worker.start)
        thread.start()
    
        def change_interval():
            value = spinbox_interval.value()
            event = IntervalEvent(value)
            QApplication.postEvent(worker, event)
    
        spinbox_interval.valueChanged.connect(change_interval)
    
        win.show()
        ret = app.exec_()
    
        QMetaObject.invokeMethod(worker.timer, "stop")
        thread.quit()
        thread.wait()
        sys.exit(ret)
    
    
    if __name__ == "__main__":
        main()
    
  • QTimer.singleShot() with functools.partial()(仅适用于 PyQt5,不适用于 PySide2)

    import sys
    from functools import partial
    
    from PyQt5.QtWidgets import QApplication, QMainWindow, QSpinBox
    from PyQt5.QtCore import QMetaObject, QObject, Qt, QTimer, QThread
    
    
    class Worker(QObject):
        def __init__(self):
            QObject.__init__(self)
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.work)
    
        def start(self):
            self.timer.start(1000)
    
        def work(self):
            print("Hello World...")
    
        def set_interval(self, interval):
            print(interval)
            self.timer.setInterval(interval)
    
    
    def main():
        # Set up main window
        app = QApplication(sys.argv)
        win = QMainWindow()
        win.setFixedSize(200, 100)
        spinbox_interval = QSpinBox(win)
        spinbox_interval.setMaximum(5000)
        spinbox_interval.setSingleStep(500)
        spinbox_interval.setValue(1000)
    
        worker = Worker()
        thread = QThread()
        worker.moveToThread(thread)
        thread.started.connect(worker.start)
        thread.start()
    
        def change_interval():
            value = spinbox_interval.value()
            wrapper = partial(worker.set_interval, value)
            QTimer.singleShot(0, wrapper)
    
        spinbox_interval.valueChanged.connect(change_interval)
    
        win.show()
        ret = app.exec_()
    
        QMetaObject.invokeMethod(worker.timer, "stop")
        thread.quit()
        thread.wait()
        sys.exit(ret)
    
    
    if __name__ == "__main__":
        main()
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何更改 Qthread 内 Qtimer 的时间间隔? 的相关文章

随机推荐

  • Rails:从 webpacker 提供的文件访问 JS 模块方法

    Context 我尝试使用 Webpacker gem 将应用程序中的资产移动到 webpack 应用程序很大 所以我需要部分完成 到目前为止做了什么 我成功地使用调用脚本javascript pack tag 我导出一个超级简单的模块 j
  • 为什么 Kotlin 中函数不能直接用作 lambda?

    在 Kotlin 中我们不能写 arrayOf 1 2 3 forEach println 但我们必须调用forEach using println 这是因为forEach期望一个 lambda 但是println是一个函数 为什么这些类型
  • 显示:Chrome 中出现了磨合?

    我尝试过使用display run in为了创建一个语义化且美观的元数据名称 值列表 喜欢这样 dl dt Subject dt dd A Question dd dt From dt dd Mr Smith dd dt dt dl
  • 防止 unlist 删除 NULL 值

    我有一个列表向量 我使用unlist在他们 向量中的一些元素是NULL and unlist似乎正在放弃它们 我怎样才能防止这种情况发生 这是一个简单 非 工作示例 展示了这一点不需要的功能 of unlist a c list p1 2
  • iPhone safari 上的奇怪点击事件气泡在冒泡到 document.body 之前停止

    我已将点击事件绑定为 document body onclick function alert aaa 无论我点击什么元素 它在 Android 上或 IOS 上的 Chrome 上都表现良好 但在 iPhone safari 上单击除 a
  • 检测变化的多对多关系

    我试图理解为什么 DbContext 没有检测到多对多关系的变化 这是我在模型配置中设置的 this Configuration ValidateOnSaveEnabled false this Configuration ProxyCre
  • 如何将 PIL 与 PyPy 一起使用?

    我进行了一些搜索 但找不到将 PIL 与 PyPy 一起使用的教程 根据 PyPy 的博客 支持 PIL 我在 PYTHONPATH 中使用 pip 安装了 PIL 下载后 pip make 2个 pyd文件 imaging pyd和 im
  • 将我自己的 SQLite DB 从 Asset 文件夹复制到

    我不明白为什么我无法将数据库文件 abic 复制到应用程序目录 data data context getPackageName databases 这是我的 DataBaseHelper 类 import java io File imp
  • 如何查明转换是否已在节点上运行?

    我怎样才能知道节点上是否已经有一个转换正在运行 例如FadeTransition 您可以随时使用过渡 http docs oracle com javafx 2 api javafx animation Transition html 状态
  • 代码契约:如何处理继承的接口?

    我正在使用 MS Code Contracts 并且在使用接口继承和 ContractClassFor 属性时遇到了障碍 给定这些接口和合约类 ContractClass typeof IOneContract interface IOne
  • IPython 3.5 返回“错误的解释器:没有这样的文件或目录”

    我在尝试使用 IPython 时遇到随机错误 我现在突然无法使用 iPython3 没有任何解释 我不记得除了以太坊客户端之外安装过任何重要的东西 而且我没有下载哈希值或任何东西 突然我明白了 cchilders ipython3 bash
  • 停止模型上的双向数据绑定

    我对 Angular 还很陌生 所以如果这里有一些不正确的想法 请告诉我 我正在尝试基于同一数据集创建两个单独的范围变量 我假设我能够将它们设置为不同的变量 如下所示 并且它会起作用 然而 我发现 无论它们的名称是什么或如何定义 即使是在指
  • 在 Python 中使用 XML 模式进行验证

    我有一个 XML 文件和另一个文件中的 XML 架构 我想验证我的 XML 文件是否遵循该架构 我如何在 Python 中做到这一点 我更喜欢使用标准库 但如果需要 我可以安装第三方包 我假设您的意思是使用 XSD 文件 令人惊讶的是 支持
  • 如何查看docker镜像的日志?

    在docker世界中 我们可以很容易地看到docker容器 即正在运行的镜像 的日志 但在图像创建过程中 通常会发出多个命令 例如 节点项目中的 npm install 命令 查看这些命令的日志也会很有帮助 我快速地从文档中搜索 但没有找到
  • 使用 PhantomJS 嵌入网页的所有图像会产生警告,但可以工作

    我试图通过嵌入所有图像 以及通过这一点后的其他外部资源 将网页转换为单个文件 以下是我运行 PhantomJs 的方式 phantomjs web security false embed images js http localhost
  • 构建代理离线

    我正在使用 TFS 2015 我看到我的构建代理处于离线状态 我启动 VsoWorker exe 来查看日志并了解错误 这是我得到的信息 但我从互联网上找不到任何内容 请问有什么想法吗 16 07 57 649004 Sending tra
  • 使用嵌套 ScrollViewer 忽略水平鼠标滚动

    我在网格周围有一个 ScrollViewer 来垂直滚动其内容
  • 键盘自动校正高度(带/不带自动校正)

    我得到的键盘高度是这样的 void keyboardNotification NSNotification notification NSDictionary keyboardInfo notification userInfo NSVal
  • 使用 CMake 进行 Boost 测试 - 未定义的 main

    我在使用 MacPorts 安装的 Boost 在 Mac 上构建一个使用 Boost Test 的小程序时遇到问题 opt local lib 这是我的最小源文件 test cpp define BOOST TEST MODULE MyT
  • 如何更改 Qthread 内 Qtimer 的时间间隔?

    我希望能够更改 QThread 内 QTimer 的间隔时间 这是我的代码 import sys from PyQt5 import QtWidgets from PyQt5 QtWidgets import QApplication QM