PyQt4 equivilent to time.sleep?

2019-02-22 16:40发布

问题:

I can't use time.sleep in my pyqt application because that freezes the GUI thread, so the GUI will be completely frozen during this time.I have been looking for a way to handle this.

I tried to use QTimer, but it seemed like they need to be linked to another function? Like wait ten seconds then run some function. Is there a way to just have it wait then continue with the current function? Thanks!

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

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

回答1:

Actually i was looking for time.sleep alternative to use in pyqt without using any thread concepts.

And the solution i figured out is:

from PyQt4 import QtTest

QtTest.QTest.qWait(msecs)

This works similar to time.sleep making GUI responsive.

Thankyou for your answers.



回答2:

Maybe it could be done better but you can always use singleShot to run function with delay, and lambda to run function with argument.

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:

I believe you are asking how to keep the GUI responsive if num() takes several seconds to run? You have two options:

  • if num() consists of many small chunks of "work", you can call application.processEvents() between the chunks, this will allow the GUI to respond to events. An easy situation to deal with is when most of the num() time is spent in a loop, then at the start or end of each iteration, call application.processEvents(). In your real application, if you don't have access to application, import qApp from PyQt4.
  • the better approach is to execute num() in a separate thread. There are many examples of this on SO (like this one). One way of doing that is

    • instantiate a QThread,
    • define a class (say NumberCruncher) that derives from QObject and defines num(self) and defines a signal 'done' emitted by num() before returning
    • call numberCruncher.moveToThread(thread)
    • connect the thread started signal to num
    • start the thread


回答4:

You cannot use time.sleep in the pyqt main event loop as it would stop the GUI event loop from responding.

A solution in pyqt could look like this, using 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_())