【问题标题】:Timers in PyQt based GUI基于 PyQt 的 GUI 中的计时器
【发布时间】:2018-08-01 05:53:29
【问题描述】:

我在一个接一个地同时运行计时器时遇到问题。下一个计时器正在运行,前一个计时器停止,到达前一个计时器开始的时间后。下面列出了有问题的代码。

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()

【问题讨论】:

    标签: python python-2.7 pyqt pyqt4


    【解决方案1】:

    time.sleep() 不应该在 GUI 中使用,因为它会阻塞 GUI 事件循环,导致不更新 GUI 等问题,除了使用输入 (),并考虑调用 processEvents() 的不良做法。

    Qt 提供 QTimer,这是一个专门用于每隔一定时间间隔调用特定任务的类。

    在下一部分中,我将展示一个示例:

    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_())
    

    【讨论】:

    • 谢谢您的回复,但是计时器没有在按钮上显示任何值
    • @amanrawat 您是否尝试过我的代码,或者您是否已将其调整为您的初始代码?你按下按钮了吗?
    • 是的,先生,我修改了您的代码并按下按钮,但仍未在按钮上显示计时器值。
    • @amanrawat 先试试我的原始代码,如果可行,问题出在你的适配,而不是我的答案。告诉我我的例子是否有效。
    • @amanrawat 好吧,它适用于我,什么版本的 python 和 pyqt4?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-22
    • 2020-03-01
    相关资源
    最近更新 更多