基于 PyQt 的 GUI 中的计时器
Timers in PyQt based GUI
我遇到了一个问题,运行 一个定时器同时被 one.The 下一个定时器 运行 和前一个定时器停止,并且在达到前一个定时器开始的时间后。下面列出了有问题的代码。
import time
from PyQt4 import QtCore, QtGui
import sys
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle("PyQT tuts!")
self.setWindowIcon(QtGui.QIcon('pythonlogo.png'))
self.home()
def home(self):
self.btn = QtGui.QPushButton(self)
self.btn.setObjectName(_fromUtf8("pb"))
self.btn.clicked.connect(self.timer)
self.btn.setText("Timer1")
self.btn.resize(65,25)
self.btn.move(100,100)
self.btn2 = QtGui.QPushButton(self)
self.btn2.setObjectName(_fromUtf8("pb2"))
self.btn2.clicked.connect(self.timer2)
self.btn2.setText("Timer2")
self.btn2.resize(65,25)
self.btn2.move(100,150)
self.btn3 = QtGui.QPushButton(self)
self.btn3.setObjectName(_fromUtf8("pb3"))
self.btn3.clicked.connect(self.timer3)
self.btn3.setText("Timer3")
self.btn3.resize(65,25)
self.btn3.move(100,200)
self.btn4 = QtGui.QPushButton(self)
self.btn4.setObjectName(_fromUtf8("pb4"))
self.btn4.clicked.connect(self.timer4)
self.btn4.setText("Timer4")
self.btn4.resize(65,25)
self.btn4.move(100,250)
self.show()
def timer(self):
# uin = input("enter the time : ")
when_to_stop = 10
# abs(int(uin))
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
# print(time_left+'\r')
time.sleep(1.0)
when_to_stop -= 1
self.btn.setText(str(time_left))
QtGui.qApp.processEvents()
def timer2(self):
# uin = input("enter the time : ")
when_to_stop = 10
# abs(int(uin))
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
# print(time_left+'\r')
time.sleep(1.0)
when_to_stop -= 1
self.btn2.setText(str(time_left))
QtGui.qApp.processEvents()
def timer3(self):
# uin = input("enter the time : ")
when_to_stop = 10
# abs(int(uin))
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
# print(time_left+'\r')
time.sleep(1.0)
when_to_stop -= 1
self.btn3.setText(str(time_left))
QtGui.qApp.processEvents()
def timer4(self):
# uin = input("enter the time : ")
when_to_stop = 10
# abs(int(uin))
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
# print(time_left+'\r')
time.sleep(1.0)
when_to_stop -= 1
self.btn4.setText(str(time_left))
QtGui.qApp.processEvents()
def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
run()
time.sleep()
不应在 GUI 中使用,因为它会阻塞 GUI 事件循环,导致诸如不更新 GUI 之类的问题,除了使用输入 () 之外,并考虑调用 processEvents()
的不良做法。
Qt 提供了 QTimer,它是一个 class 专门用于每隔特定时间间隔调用特定任务。
在下一部分中,我将展示一个示例:
import sys
from PyQt4 import QtCore, QtGui
from functools import partial
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
centralwidget = QtGui.QWidget()
self.setCentralWidget(centralwidget)
layout = QtGui.QVBoxLayout(centralwidget)
for i in range(4):
button = QtGui.QPushButton("Timer{}".format(i+1))
layout.addWidget(button)
button.clicked.connect(partial(self.onClicked, button))
def onClicked(self, button):
sec = 10 # seconds
timer = button.property("timer").toPyObject()
if timer is None:
timer = QtCore.QTimer(button)
timer.stop()
timer.setInterval(1000)
timer.setProperty("button", button)
timer.setProperty("endTime", QtCore.QTime.currentTime().addMSecs(sec*1000+10))
timer.timeout.connect(partial(self.onTimeout, timer))
self.onTimeout(timer)
timer.start()
button.setProperty("timer", timer)
def onTimeout(self, timer):
button= timer.property("button")
if hasattr(button, 'toPyObject'):
button = button.toPyObject()
tm = timer.property("endTime").toPyObject()
if hasattr(tm, 'toPyObject'):
tm = tm.toPyObject()
ms = QtCore.QTime.currentTime().msecsTo(tm)
if ms < 0:
timer.stop()
else:
button.setText(QtCore.QTime().addMSecs(ms).toString())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())
我遇到了一个问题,运行 一个定时器同时被 one.The 下一个定时器 运行 和前一个定时器停止,并且在达到前一个定时器开始的时间后。下面列出了有问题的代码。
import time
from PyQt4 import QtCore, QtGui
import sys
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle("PyQT tuts!")
self.setWindowIcon(QtGui.QIcon('pythonlogo.png'))
self.home()
def home(self):
self.btn = QtGui.QPushButton(self)
self.btn.setObjectName(_fromUtf8("pb"))
self.btn.clicked.connect(self.timer)
self.btn.setText("Timer1")
self.btn.resize(65,25)
self.btn.move(100,100)
self.btn2 = QtGui.QPushButton(self)
self.btn2.setObjectName(_fromUtf8("pb2"))
self.btn2.clicked.connect(self.timer2)
self.btn2.setText("Timer2")
self.btn2.resize(65,25)
self.btn2.move(100,150)
self.btn3 = QtGui.QPushButton(self)
self.btn3.setObjectName(_fromUtf8("pb3"))
self.btn3.clicked.connect(self.timer3)
self.btn3.setText("Timer3")
self.btn3.resize(65,25)
self.btn3.move(100,200)
self.btn4 = QtGui.QPushButton(self)
self.btn4.setObjectName(_fromUtf8("pb4"))
self.btn4.clicked.connect(self.timer4)
self.btn4.setText("Timer4")
self.btn4.resize(65,25)
self.btn4.move(100,250)
self.show()
def timer(self):
# uin = input("enter the time : ")
when_to_stop = 10
# abs(int(uin))
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
# print(time_left+'\r')
time.sleep(1.0)
when_to_stop -= 1
self.btn.setText(str(time_left))
QtGui.qApp.processEvents()
def timer2(self):
# uin = input("enter the time : ")
when_to_stop = 10
# abs(int(uin))
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
# print(time_left+'\r')
time.sleep(1.0)
when_to_stop -= 1
self.btn2.setText(str(time_left))
QtGui.qApp.processEvents()
def timer3(self):
# uin = input("enter the time : ")
when_to_stop = 10
# abs(int(uin))
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
# print(time_left+'\r')
time.sleep(1.0)
when_to_stop -= 1
self.btn3.setText(str(time_left))
QtGui.qApp.processEvents()
def timer4(self):
# uin = input("enter the time : ")
when_to_stop = 10
# abs(int(uin))
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
# print(time_left+'\r')
time.sleep(1.0)
when_to_stop -= 1
self.btn4.setText(str(time_left))
QtGui.qApp.processEvents()
def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
run()
time.sleep()
不应在 GUI 中使用,因为它会阻塞 GUI 事件循环,导致诸如不更新 GUI 之类的问题,除了使用输入 () 之外,并考虑调用 processEvents()
的不良做法。
Qt 提供了 QTimer,它是一个 class 专门用于每隔特定时间间隔调用特定任务。
在下一部分中,我将展示一个示例:
import sys
from PyQt4 import QtCore, QtGui
from functools import partial
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
centralwidget = QtGui.QWidget()
self.setCentralWidget(centralwidget)
layout = QtGui.QVBoxLayout(centralwidget)
for i in range(4):
button = QtGui.QPushButton("Timer{}".format(i+1))
layout.addWidget(button)
button.clicked.connect(partial(self.onClicked, button))
def onClicked(self, button):
sec = 10 # seconds
timer = button.property("timer").toPyObject()
if timer is None:
timer = QtCore.QTimer(button)
timer.stop()
timer.setInterval(1000)
timer.setProperty("button", button)
timer.setProperty("endTime", QtCore.QTime.currentTime().addMSecs(sec*1000+10))
timer.timeout.connect(partial(self.onTimeout, timer))
self.onTimeout(timer)
timer.start()
button.setProperty("timer", timer)
def onTimeout(self, timer):
button= timer.property("button")
if hasattr(button, 'toPyObject'):
button = button.toPyObject()
tm = timer.property("endTime").toPyObject()
if hasattr(tm, 'toPyObject'):
tm = tm.toPyObject()
ms = QtCore.QTime.currentTime().msecsTo(tm)
if ms < 0:
timer.stop()
else:
button.setText(QtCore.QTime().addMSecs(ms).toString())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())