2016-06-26 171 views
1

所以我想创建一个计时器或排序,启动按钮启动计时器,我需要停止计时器与停止按钮,然后记录时间...我可以似乎没有想到如何在计时器功能启动后停止。我试过如果语句,disconnect()和其他许多... 我意识到在qt中有一个计时器,但我试图找出这种方式。谢谢。使用“停止按钮”退出功能

import sys 
import time 
from PyQt4 import QtCore, QtGui, uic 

form_class = uic.loadUiType("/Users/Home/Desktop/Timer/timer.ui")[0] 


class MyWindowClass(QtGui.QMainWindow, form_class): 
    def __init__(self, parent=None): 
     QtGui.QMainWindow.__init__(self, parent) 
     self.setupUi(self) 
     self.startButton.clicked.connect(self.timer) 

    def timer(self): 
     timeL = 0 
     self.stopButton.clicked.connect(False) 
     while True: 
      self.timeView.display(timeL) 
      timeL = timeL + 1 
      time.sleep(1) 
      app.processEvents() 


app = QtGui.QApplication(sys.argv) 
myWindow = MyWindowClass(None) 
myWindow.show() 
app.exec_() 

回答

0

使用标志来控制循环。然后复位标志连接到停止按钮槽:

 self.startButton.clicked.connect(self.timer) 
     self.stopButton.clicked.connect(self.stop) 

    def stop(self): 
     self._timer_flag = False 

    def timer(self): 
     timeL = 0 
     self._timer_flag = True 
     while self._timer_flag: 
      self.timeView.display(timeL) 
      timeL = timeL + 1 
      time.sleep(1) 
      app.processEvents() 

QTimer比较好,因为在更新UI没有滞后。但是你可以通过使用内循环调用processEvents更频繁地提高你的例子:

def timer(self): 
     timeL = 0 
     self._timer_flag = True 
     while self._timer_flag: 
      self.timeView.display(timeL) 
      timeL = timeL + 1 
      for _ in range(10): 
       # process events for up to 50 milliseconds 
       app.processEvents(QtCore.QEventLoop.AllEvents, 50) 
       time.sleep(0.1) 
+0

这绝对是可怕的建议,完全忽略了这一点。 OP要测量时间的流逝。事件循环和定时器('QTimer')不在其中任何位置。操作系统已经在测量时间的进展。只是问问吧! 'QElapsedTimer'是你想要使用的api。 –

+0

这种方法很有效,但它是一种非常可恶的混合物,这个答案的唯一用途就是精确地显示**如何不这样做。如果你看到任何这样的代码,跑掉(或者更好的解决它)。 –

+0

@KubaOber。我认为OP已经明白有更好的选择可供选择。我读这个问题的方式是,他们只是想知道如何解决他们的示例代码。正如你所说,它**确实有效:所以我没有看到在这个基础上回答它的任何伤害。我给出的小小建议完全**针对OP的示例代码,所以我很乐意支持它。 (坦率地说,它从来没有想过任何人会像你看起来那样认真对待这样的示例代码)。 – ekhumoro

-2

听起来就像你想在QThread上使用QTimer。 这个答案应该给你你需要的一切。 https://stackoverflow.com/a/18960953/5757280

+0

这不需要'QThread',只是一个计时器。 –

+0

如果你想让QTimer在非gui线程中运行,你应该使用QThread? –

+0

他只需要定期执行一些行为。不需要辅助线程。 –

2

TL; DR:你以后QElapsedTimer,不QTimer

操作系统已经在为您测量时间的流逝。你自己不会做得更好。

“我试图找出这种方式” - 它会比使用QElapsedTimer更不准确,因为您认为已经过去了很长的时间,因为您希望睡觉。这几乎从未如此:通过的实际时间量与sleep的参数不同。更糟糕的是,这些错误通常也是系统性的,所以你的时间积累会有偏差,随着时间的推移会变得不准确。所以,不要这样做。这个不成立。也许你并没有告诉我们你究竟想要做什么:如果你问的是一个不起作用的特定解决方案,这有助于说明解决方案应该是什么问题。 为什么你想搞清楚这个(错误)的方式?

有概念上三种不同的定时器的Qt的:

  1. QElapsedTimer就像一个秒表:它是测量时间的流逝的操作系统的方法的接口。这是您应该用来衡量按钮点击之间经过多少时间的课程。

  2. QTime就像一个挂钟:你可以问它几点,通过currentTime(),并获取两次读数之间的时间差来获得流逝的时间。只有当您需要知道绝对时间时才使用此类,否则QElapsedTimer将为经过时间测量提供更好的分辨率。

  3. QTimer是超时的来源:它是定期调用您的代码的一种方式。这并不意味着用于测量时间,而仅仅是让你的代码周期性运行,例如当你想刷新屏幕显示,或实现一个周期性发出蜂鸣声的节拍器。我们不保证您的代码会按时被调用,也不保证不会错过某些代码。你想保证它,你需要写一个内核驱动程序,没有办法。

下面是一个使用PyQt4的完整示例,适用于Python 3.5。它使用QElapsedTimer来测量按钮按下之间的时间流逝,并使用QTimer来保持时间显示刷新。

#!/usr/bin/env python 
#https://github.com/KubaO/stackoverflown/tree/master/questions/interval-timer-38036583 
# -*- coding: utf-8 -*- 
import sys 
from PyQt4 import QtCore, QtGui 

if __name__ == "__main__": 
    running = False 
    app = QtGui.QApplication(sys.argv) 
    w = QtGui.QWidget() 
    layout = QtGui.QVBoxLayout(w) 
    label = QtGui.QLabel() 
    button = QtGui.QPushButton('Start') 
    timer = QtCore.QElapsedTimer() 
    updateTimer = QtCore.QTimer() 

    layout.addWidget(label) 
    layout.addWidget(button) 

    def onTimeout(): 
     label.setText('Elapsed: {0}ms'.format(timer.elapsed())) 

    def onClicked(): 
     global running 
     if running: 
      onTimeout() 
      updateTimer.stop() 
      button.setText('Start') 
     else: 
      timer.start() 
      updateTimer.start() 
      button.setText('Stop') 
     running = not running 

    updateTimer.setInterval(1000/25) # ~25fps update rate 
    updateTimer.timeout.connect(onTimeout) 
    button.clicked.connect(onClicked) 

    w.show() 
    sys.exit(app.exec_()) 
+0

非常感谢,这非常有帮助。我对qt是新手,只是尝试了一些我可以在当前工作中实现的东西(尚未编程),所以好的和坏的都是有用的。再次感谢。 –