Maarij K.
Maarij K.

Reputation: 23

How to stop PyQt timer from constantly resetting

I am trying to make a PyQt timer application for a project. I have designed the layout using QtDesigner and I am almost finished with all the code. There is just one small problem. I want to make a stop button for my timer, but everytime I make it the timer resets itself as soon as I press start again. I want it to continue as long as the timer has not already timed out. I did partially fix it once, meaning the timer did continue, but the problem with that was that the numbers went into the negatives instead of just stopping on zero. I am very new to Python and even more so to PyQt, so I am sorry if the solution seems obvious (I spent days trying to figure it out).

Anyways here is the code (the one where it resets itself):

from PyQt4 import QtCore, QtGui
import time
from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT

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 Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(351, 200)
        MainWindow.setMinimumSize(QtCore.QSize(0, 200))
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(_fromUtf8("../../../Pictures/clock-icon-md.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.gridLayout = QtGui.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.display = QtGui.QLCDNumber(self.centralwidget)
        font = QtGui.QFont()
        font.setKerning(True)
        self.display.setFont(font)
        self.display.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.display.setAutoFillBackground(False)
        self.display.setFrameShape(QtGui.QFrame.Box)
        self.display.setFrameShadow(QtGui.QFrame.Raised)
        self.display.setMidLineWidth(-2)
        self.display.setSmallDecimalPoint(False)
        self.display.setNumDigits(5)
        self.display.setDigitCount(5)
        self.display.setMode(QtGui.QLCDNumber.Dec)
        self.display.setSegmentStyle(QtGui.QLCDNumber.Filled)
        self.display.setProperty("value", 0.0)
        self.display.setProperty("intValue", 0)
        self.display.setObjectName(_fromUtf8("display"))
        self.gridLayout.addWidget(self.display, 0, 0, 1, 5)
        self.minBox = QtGui.QSpinBox(self.centralwidget)
        self.minBox.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
        self.minBox.setMaximum(60)
        self.minBox.setObjectName(_fromUtf8("minBox"))
        self.gridLayout.addWidget(self.minBox, 2, 0, 1, 1)
        self.secBox = QtGui.QSpinBox(self.centralwidget)
        self.secBox.setMaximum(60)
        self.secBox.setObjectName(_fromUtf8("secBox"))
        self.gridLayout.addWidget(self.secBox, 2, 1, 1, 1)
        self.secLabel = QtGui.QLabel(self.centralwidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.secLabel.sizePolicy().hasHeightForWidth())
        self.secLabel.setSizePolicy(sizePolicy)
        self.secLabel.setObjectName(_fromUtf8("secLabel"))
        self.gridLayout.addWidget(self.secLabel, 3, 1, 1, 1)
        self.minLabel = QtGui.QLabel(self.centralwidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.minLabel.sizePolicy().hasHeightForWidth())
        self.minLabel.setSizePolicy(sizePolicy)
        self.minLabel.setObjectName(_fromUtf8("minLabel"))
        self.gridLayout.addWidget(self.minLabel, 3, 0, 1, 1)
        self.startBtn = QtGui.QPushButton(self.centralwidget)
        self.startBtn.setObjectName(_fromUtf8("startBtn"))
        self.gridLayout.addWidget(self.startBtn, 2, 2, 1, 1)
        self.ResetBtn = QtGui.QPushButton(self.centralwidget)
        self.ResetBtn.setWhatsThis(_fromUtf8(""))
        self.ResetBtn.setObjectName(_fromUtf8("ResetBtn"))
        self.gridLayout.addWidget(self.ResetBtn, 2, 4, 1, 1)
        self.stopBtn = QtGui.QPushButton(self.centralwidget)
        self.stopBtn.setObjectName(_fromUtf8("stopBtn"))
        self.gridLayout.addWidget(self.stopBtn, 2, 3, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 351, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.msgBox = QtGui.QMessageBox()
        self.msgBox.setWindowTitle('Finished')
        self.msgBox.setIcon (QtGui.QMessageBox.Information)
        self.msgBox.setText("Time Out !!")
        stopButton = self.msgBox.addButton("Stop", QtGui.QMessageBox.ActionRole)
        ignoreButton = self.msgBox.addButton(QtGui.QMessageBox.Ignore)

        self.started = False

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.home()

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "Timer Application", None))
        self.secLabel.setText(_translate("MainWindow", "Seconds", None))
        self.minLabel.setText(_translate("MainWindow", "Minutes", None))
        self.startBtn.setToolTip(_translate("MainWindow", "<html><head/><body><p>Start the timer</p></body></html>", None))
        self.startBtn.setStatusTip(_translate("MainWindow", "Start the timer", None))
        self.startBtn.setText(_translate("MainWindow", "Start", None))
        self.ResetBtn.setToolTip(_translate("MainWindow", "<html><head/><body><p>Reset the timer</p></body></html>", None))
        self.ResetBtn.setStatusTip(_translate("MainWindow", "Reset the timer", None))
        self.ResetBtn.setText(_translate("MainWindow", "Reset", None))
        self.stopBtn.setToolTip(_translate("MainWindow", "<html><head/><body><p>Stop the timer</p></body></html>", None))
        self.stopBtn.setStatusTip(_translate("MainWindow", "Stop the timer", None))
        self.stopBtn.setText(_translate("MainWindow", "Stop", None))

    def home(self):
        self.startBtn.clicked.connect(self.value_calc)
        self.stopBtn.clicked.connect(self.stop_timer)
        self.ResetBtn.clicked.connect(self.reset_timer)



    def stop_timer(self):
        self.timer.stop()
        if self.value != -1:
            self.started = True
        else:
            self.started = False



    def displayer(self):
        self.display.display(self.value)
        self.value -= 1


    if self.value == -1:
            self.display.display(0)
            self.timer.stop()

            self.msgBox.show()




    def value_calc(self):
        sec_value = self.secBox.value()
        min_value = self.minBox.value()
        min_value *= 60
        self.value = sec_value + min_value
        if self.value != -1:
            if self.started == False:
                self.timer = QtCore.QTimer()
                self.timer.timeout.connect(self.displayer)
                self.timer.start(1000)
            else:
                self.timer.start(1000)
        else:
            pass

    def reset_timer(self):
        self.timer.stop()
        self.display.display(0)


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Upvotes: 1

Views: 1807

Answers (1)

danidee
danidee

Reputation: 9624

You have a lot of unnecessary if statements in your program and an unnecessary variable called self.started. Also you need a way to tell your value_calc function to check the current value of self.value, this can only be achieved by setting a default value for self.value in your home function (you should actually be using __init__ for that) also when you press the reset button you also need to reset self.value back to it's initial value so you don't start counting from where it stopped, this also prevents your timer from counting into negative values because there will always be a check in value_calc to check if the self.value is less than zero

Here is the final code:

from PyQt4 import QtCore, QtGui
import time
from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT

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 Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(351, 200)
        MainWindow.setMinimumSize(QtCore.QSize(0, 200))
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(_fromUtf8("../../../Pictures/clock-icon-md.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.gridLayout = QtGui.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.display = QtGui.QLCDNumber(self.centralwidget)
        font = QtGui.QFont()
        font.setKerning(True)
        self.display.setFont(font)
        self.display.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.display.setAutoFillBackground(False)
        self.display.setFrameShape(QtGui.QFrame.Box)
        self.display.setFrameShadow(QtGui.QFrame.Raised)
        self.display.setMidLineWidth(-2)
        self.display.setSmallDecimalPoint(False)
        self.display.setNumDigits(5)
        self.display.setDigitCount(5)
        self.display.setMode(QtGui.QLCDNumber.Dec)
        self.display.setSegmentStyle(QtGui.QLCDNumber.Filled)
        self.display.setProperty("value", 0.0)
        self.display.setProperty("intValue", 0)
        self.display.setObjectName(_fromUtf8("display"))
        self.gridLayout.addWidget(self.display, 0, 0, 1, 5)
        self.minBox = QtGui.QSpinBox(self.centralwidget)
        self.minBox.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
        self.minBox.setMaximum(60)
        self.minBox.setObjectName(_fromUtf8("minBox"))
        self.gridLayout.addWidget(self.minBox, 2, 0, 1, 1)
        self.secBox = QtGui.QSpinBox(self.centralwidget)
        self.secBox.setMaximum(60)
        self.secBox.setObjectName(_fromUtf8("secBox"))
        self.gridLayout.addWidget(self.secBox, 2, 1, 1, 1)
        self.secLabel = QtGui.QLabel(self.centralwidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.secLabel.sizePolicy().hasHeightForWidth())
        self.secLabel.setSizePolicy(sizePolicy)
        self.secLabel.setObjectName(_fromUtf8("secLabel"))
        self.gridLayout.addWidget(self.secLabel, 3, 1, 1, 1)
        self.minLabel = QtGui.QLabel(self.centralwidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.minLabel.sizePolicy().hasHeightForWidth())
        self.minLabel.setSizePolicy(sizePolicy)
        self.minLabel.setObjectName(_fromUtf8("minLabel"))
        self.gridLayout.addWidget(self.minLabel, 3, 0, 1, 1)
        self.startBtn = QtGui.QPushButton(self.centralwidget)
        self.startBtn.setObjectName(_fromUtf8("startBtn"))
        self.gridLayout.addWidget(self.startBtn, 2, 2, 1, 1)
        self.ResetBtn = QtGui.QPushButton(self.centralwidget)
        self.ResetBtn.setWhatsThis(_fromUtf8(""))
        self.ResetBtn.setObjectName(_fromUtf8("ResetBtn"))
        self.gridLayout.addWidget(self.ResetBtn, 2, 4, 1, 1)
        self.stopBtn = QtGui.QPushButton(self.centralwidget)
        self.stopBtn.setObjectName(_fromUtf8("stopBtn"))
        self.gridLayout.addWidget(self.stopBtn, 2, 3, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 351, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.msgBox = QtGui.QMessageBox()
        self.msgBox.setWindowTitle('Finished')
        self.msgBox.setIcon (QtGui.QMessageBox.Information)
        self.msgBox.setText("Time Out !!")
        stopButton = self.msgBox.addButton("Stop", QtGui.QMessageBox.ActionRole)
        ignoreButton = self.msgBox.addButton(QtGui.QMessageBox.Ignore)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.home()

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "Timer Application", None))
        self.secLabel.setText(_translate("MainWindow", "Seconds", None))
        self.minLabel.setText(_translate("MainWindow", "Minutes", None))
        self.startBtn.setToolTip(_translate("MainWindow", "<html><head/><body><p>Start the timer</p></body></html>", None))
        self.startBtn.setStatusTip(_translate("MainWindow", "Start the timer", None))
        self.startBtn.setText(_translate("MainWindow", "Start", None))
        self.ResetBtn.setToolTip(_translate("MainWindow", "<html><head/><body><p>Reset the timer</p></body></html>", None))
        self.ResetBtn.setStatusTip(_translate("MainWindow", "Reset the timer", None))
        self.ResetBtn.setText(_translate("MainWindow", "Reset", None))
        self.stopBtn.setToolTip(_translate("MainWindow", "<html><head/><body><p>Stop the timer</p></body></html>", None))
        self.stopBtn.setStatusTip(_translate("MainWindow", "Stop the timer", None))
        self.stopBtn.setText(_translate("MainWindow", "Stop", None))

    def home(self):
        self.startBtn.clicked.connect(self.value_calc)
        self.stopBtn.clicked.connect(self.stop_timer)
        self.ResetBtn.clicked.connect(self.reset_timer)
        self.value = -1



    def stop_timer(self):
        self.timer.stop()


    def displayer(self):
        self.display.display(self.value)
        self.value -= 1

        if self.value == -1:
            self.display.display(0)
            self.timer.stop()
            self.msgBox.show()




    def value_calc(self):
        if self.value < 0:
            sec_value = self.secBox.value()
            min_value = self.minBox.value()
            min_value *= 60
            self.value = sec_value + min_value
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.displayer)
            self.timer.start(1000)
        else:
            self.timer.start(1000)

    def reset_timer(self):
        self.timer.stop()
        self.display.display(0)
        self.value = -1

Also just for next time when comparing Boolean Values in python

if x == True or if x == False

is equivalent to

if x or if not x

Upvotes: 1

Related Questions