等效于 PyQt 应用程序的 time.sleep

Posted

技术标签:

【中文标题】等效于 PyQt 应用程序的 time.sleep【英文标题】:Equivalent to time.sleep for a PyQt application 【发布时间】:2017-01-09 09:59:31 【问题描述】:

我无法在我的 pyqt 应用程序中使用 time.sleep,因为这会冻结 GUI 线程,因此在此期间 GUI 将完全冻结。我一直在寻找一种方法来处理这个问题。

我尝试使用 QTimer,但似乎需要将它们链接到另一个函数?就像等待十秒钟然后运行一些功能。有没有办法让它等待然后继续当前功能?

def num(self):
    for i in range(1,999):
        print i
        #Add some sleep here

def testSleep(self):
    QtCore.QTimer.singleShot(2000, self.num)

【问题讨论】:

将当前函数拆分为两个函数并使用QTimer 函数被一次又一次地执行 见文档QTimer - 它有方法singleShot() 最好添加有问题的小型工作示例 - 它会更具可读性,每个人都可以运行它并查看您的问题。 对我来说,你应该使用QTimer 而不是for-loop 类似if run_again: singleShot(2000, self.num) 【参考方案1】:

实际上,我正在寻找在 pyqt 中使用的 time.sleep 替代方案,而不使用任何线程概念。

我想出的解决方案是:

from PyQt4 import QtTest

QtTest.QTest.qWait(msecs)

这类似于 time.sleep 使 GUI 响应。

感谢您的回答。

【讨论】:

测试套件或应用程序需要这个吗? 它的应用程序。 那么使用QtTest是不合适的,它是用于单元测试的。另外,如果可以通过QtTset完成,也可以直接在PyQt中完成。如果您需要等待一段时间(在尝试某事之前)而不阻塞您使用QTimer.singleShot() 的 GUI。您的回答意味着高级 PyQt 用户的其他 3 个回答都不足够,这意味着您的问题没有明确说明。您应该澄清它,或者,如果您不能这样做,请将其删除。 这个解决方案对我来说非常有效,无论它是否适合使用。我只需要一个简单的睡眠,没有什么比这更复杂的了。如果 PyQt 中缺少这一点(测试除外),那么我宁愿使用它而不是实现任何比必要更复杂的东西。 使用 PyQt5 为我工作。【参考方案2】:

也许它可以做得更好,但您始终可以使用 singleShot 延迟运行函数,并使用 lambda 运行带参数的函数。

import sys
from PyQt4 import QtGui, QtCore

#def num(self, i):
def num(i):
    print i
    i += 1
    if i < 999:
        # run again after 2000ms with argument
        QtCore.QTimer.singleShot(2000, lambda:num(i))
        #QtCore.QTimer.singleShot(2000, lambda:self.num(i))

app = QtGui.QApplication(sys.argv)

# run first time with start argument
num(1)
#QtCore.QTimer.singleShot(2000, lambda:num(1))

sys.exit(app.exec_())

【讨论】:

【参考方案3】:

另一种选择是在等待时处理 Qt 事件:

def num():
    for i in range(1, 999):
        print(i)
        # Sleep five seconds in total
        for _ in range(5 * 10):
            # Process events between short sleep periods
            QtWidgets.QApplication.processEvents()
            time.sleep(0.1)

【讨论】:

【参考方案4】:

我相信您在问如果 num() 需要几秒钟才能运行,如何保持 GUI 响应?你有两个选择:

如果num() 由许多小块“工作”组成,您可以在块之间调用application.processEvents(),这将允许GUI 响应事件。一个容易处理的情况是当num() 的大部分时间花在一个循环中时,然后在每次迭代的开始或结束时调用application.processEvents()。在您的实际应用程序中,如果您无权访问 application,请从 PyQt4 导入 qApp

更好的方法是在单独的线程中执行num()。 SO上有很多这样的例子(比如this one)。一种方法是

实例化一个QThread, 定义一个派生自QObject 的类(例如NumberCruncher)并定义num(self) 并在返回之前定义num() 发出的“完成”信号 致电numberCruncher.moveToThread(thread) 将线程started信号连接到num 启动线程

【讨论】:

实际上我在这里描述的 num() 函数在内部导入了多个脚本,因此在每个不同的脚本中基于响应添加适当的睡眠时间是必要的。这使 GUI 挂起。即使我在这里也无法实现线程概念,因为它涉及许多代码更改。所以我试图在 Pyqt 中替代睡眠。【参考方案5】:

您不能在 pyqt 主事件循环中使用 time.sleep,因为它会阻止 GUI 事件循环响应。

pyqt 中的解决方案可能如下所示,使用 QTimer

import sys
from PyQt4 import QtGui, QtCore

application = QtGui.QApplication(sys.argv)

i=0
timer = QtCore.QTimer()

def num():
    global i, timer
    if i <999:
        print ( i )
        i += 1
    else:
        timer.stop()

timer.timeout.connect(num)
timer.start(2000)

sys.exit(application.exec_())

【讨论】:

以上是关于等效于 PyQt 应用程序的 time.sleep的主要内容,如果未能解决你的问题,请参考以下文章

等效于 PyQt 应用程序的 time.sleep

等效于 PyQt 应用程序的 time.sleep

time.sleep() 和背景 Windows PyQt5

我需要python time.sleep()在C#中等效

具有任意类型参数的 PyQt 信号 / PyQt_PyObject 等效于新型信号

PyQt5 等效于 QtWebEngineWidgets.QWebEngineView() 的 QtWebKitWidgets.QWebView.page.mainFrame()?