Can't seem to get pyqt countdown timer to work

2019-07-26 05:04发布

I've searched internet for days but can figure out how to put this code to work. It's a very simple gui (made on Qt Designer) with a lcd and a button. I want it to on the press of the button to start the countdown from 180 seconds back. In the first moment i was able to make to button decrease in one the value but after trying so many different things nothing is working. Can someone help me please? Probably is something very simple. Thank you.

# -*- coding: utf-8 -*-
import sys
import time
from PyQt4 import QtCore, QtGui
from relogio import Ui_relogiocc

class StartQT4(QtGui.QMainWindow):
 def __init__(self, parent=None):
  QtGui.QWidget.__init__(self, parent)
  self.ui = Ui_relogiocc()
  self.ui.setupUi(self)
  self.timer = QtCore.QTimer()
  text = "%d:%02d" % (180/60,180 % 60)
  self.ui.QLCDNumber.display(text)
  self.timer.start(1000)
  self.ui.iniciar.clicked.connect(self.updateTimerDisplay)


 def updateTimerDisplay(self):
  self.inicio = 180
  while self.inicio != 0:
   text = "%d:%02d" % (self.inicio/60,self.inicio % 60)
   self.ui.QLCDNumber.display(text)
   self.inicio - 1
  else:
   self.timer.stop()  


if __name__ == "__main__":
 app = QtGui.QApplication(sys.argv)
 myapp = StartQT4()
 myapp.show()
 sys.exit(app.exec_())

3条回答
Ridiculous、
2楼-- · 2019-07-26 05:12

It seems there are a number of things you are missing here.

Firstly, the timer emits a timeout() signal whenever each timeout period completes. In your case, this is every one second. However, you're not connecting this signal to anything.

Secondly, your updateTimerDisplay contains the following line:

   self.inicio - 1

This reads the value of self.inicio, subtracts 1 from it and then throws the result away. Because self.inicio's value doesn't change your updateTimerDisplay method goes into an infinite loop.

I'm guessing you meant

   self.inicio -= 1

instead, which assigns the new value of self.inicio back to itself.

Ultimately, however, it seems you're trying to use your updateTimerDisplay method to start the timer, count it down and also update the display of the timer. I'd recommend breaking this method up to smaller methods.

Firstly, updateTimerDisplay should only update the display of the timer:

 def updateTimerDisplay(self):
  text = "%d:%02d" % (self.inicio/60,self.inicio % 60)
  self.ui.QLCDNumber.display(text)

Secondly, you'll want a method to start the timer. Something like the following should do:

 def startTimer(self):
  self.inicio = 180
  self.updateTimerDisplay()
  self.timer.start(1000)

Of course, you'll also need to connect your iniciar button's clicked() signal to this function, instead of to updateTimerDisplay.

Finally, you'll need a method that handles a tick from the timer. Something like the following should do:

 def timerTick(self):
  self.inicio -= 1
  self.updateTimerDisplay()
  if self.inicio <= 0:
   self.timer.stop()

You'll also need to connect the timeout() signal of the timer to this function, using something like:

  self.timer.timeout.connect(self.timerTick)
查看更多
在下西门庆
3楼-- · 2019-07-26 05:16

As it has been told in the other answers your code contains some obvious mistakes. Here you have a complete working example (the UI is not created via Designer) that resets properly the counter every time the button is clicked (i.e. stops the timer before starting it again. If you don't do that and click the Start button before the timer has stopped then the counter counts faster for every button click).

from PyQt4.QtGui import *
from PyQt4.QtCore import *

class MyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.central = QWidget(self)
        self.hbox = QHBoxLayout(self.central)
        self.lcd = QLCDNumber(self.central)
        self.timer = QTimer(self)
        self.start_time = 20
        self.lcd.display("%d:%02d" % (self.start_time/60,self.start_time % 60))
        self.start_button = QPushButton("Start", self.central)
        self.hbox.addWidget(self.lcd)
        self.hbox.addWidget(self.start_button)
        self.setCentralWidget(self.central)

        self.start_button.clicked.connect(self.restartTimer)
        self.timer.timeout.connect(self.updateLCD)

    def restartTimer(self):
        # Reset the timer and the lcd
        self.timer.stop()
        self.start_time = 20
        self.lcd.display("%d:%02d" % (self.start_time/60,self.start_time % 60))
        # Restart the timer
        self.timer.start(1000)

    def updateLCD(self):
        # Update the lcd
        self.start_time -= 1
        if self.start_time >= 0:
            self.lcd.display("%d:%02d" % (self.start_time/60,self.start_time % 60))
        else:
            self.timer.stop()

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    ui = MyMainWindow()
    ui.show()
    sys.exit(app.exec_())
查看更多
Evening l夕情丶
4楼-- · 2019-07-26 05:36

There are multiple things wrong with your code. For starters, you wrote self.inicio - 1 instead of -= 1, and you never actually use the Qtimer you create. But ignoring that, the structure of your program isn't right: Currently you call updateTimerDisplay when the user clicks your iniciar button and loop in there until your countdown reaches zero. What you want to do is start the timer when the user clicks the button and connect the timer (actually its timeout signal) to a method that just counts down one second and updates the display:

def startTimerDisplay(self):
    """ set the countdown value and start the timer """
    self.inicio = 180
    self.timer.start(1000)

def updateTimerDisplay(self):
    """ count down one second, set the text, and check if the timer should stop """
    self.inicio -= 1
    text = "%d:%02d" % (self.inicio/60,self.inicio % 60)
    self.ui.QLCDNumber.display(text)
    if self.inicio == 0:
        self.timer.stop()

Alter your __init__ method to connect these functions like this:

def __init__(self, parent=None):
    QtGui.QWidget.__init__(self, parent)
    self.ui = Ui_relogiocc()
    self.ui.setupUi(self)
    self.timer = QtCore.QTimer()
    text = "%d:%02d" % (180/60,180 % 60)
    self.ui.QLCDNumber.display(text)
    #connect the button to the start method ...
    self.ui.iniciar.clicked.connect(self.startTimerDisplay)
    #... and the timer to the update method
    self.timer.timeout.connect(self.updateTimerDisplay)
查看更多
登录 后发表回答