每当单击按钮时如何重置计时器

Posted

技术标签:

【中文标题】每当单击按钮时如何重置计时器【英文标题】:How to reset timer whenever a pushbutton is clicked 【发布时间】:2018-09-25 10:51:01 【问题描述】:

当下面的函数运行时,我的代码中有两个按钮,它启动一个计时器并禁用另一个按钮。现在简要分解正在发生的事情: 按下 OuterSwitch 按钮,检查以确保内门关闭,然后打开外门。当再次按下 OuterSwitch 按钮时,它现在禁用内部开关按钮并锁定外门。这也会启动一个 3 秒的计时器。现在,如果我此时按下外部开关打开外门,我希望它停止计时器并重置它,所以当我再次按下关闭门时,它从 3 秒开始。目前,当我再次关门时,它只会并行运行多个计时器。我一直在尝试无济于事,希望有人可以指导我如何做到这一点?如果需要更多信息,我希望这是有道理的,请询问。

import sys
import board
import RPi.GPIO as GPIO
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPixmap, QColor, QPalette
from PyQt5.QtWidgets import QApplication
import time
from functools import partial
from threading import Thread


Outer = 22
Inner = 27
GPIO.setup(Outer,GPIO.OUT)
GPIO.setup(Inner,GPIO.OUT)
GPIO.output(Outer,GPIO.HIGH)
GPIO.output(Inner,GPIO.HIGH)




class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.Timer = QtWidgets.QLCDNumber(self.centralwidget)
        self.Timer.setObjectName("Timer")
        self.horizontalLayout.addWidget(self.Timer)
        self.OuterSwitch = QtWidgets.QPushButton(self.centralwidget)
        self.OuterSwitch.setObjectName("OuterSwitch")
        self.horizontalLayout.addWidget(self.OuterSwitch)
        self.InnerSwitch = QtWidgets.QPushButton(self.centralwidget)
        self.InnerSwitch.setObjectName("InnerSwitch")
        self.horizontalLayout.addWidget(self.InnerSwitch)
        self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)




    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.OuterSwitch.setText(_translate("MainWindow", "Open Outer Door"))
        self.InnerSwitch.setText(_translate("MainWindow", "Open Inner Door"))





class ControlMainWindow(QtWidgets.QMainWindow):
    def __init__(self,parent=None):
        super(ControlMainWindow,self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.OuterSwitch.clicked.connect(self.OuterControl)
        self.ui.InnerSwitch.clicked.connect(self.InnerControl)


    def OuterControl(self):
        if GPIO.input(Inner)==0: #InnerDoorOpen
            return GPIO.output(Outer,GPIO.HIGH),print("Please Close Inner Door")
        elif GPIO.input(Outer) ==1: #Outer Door Close
            self.ui.OuterSwitch.setText(QtWidgets.QApplication.translate("MainWindow", "Close Outer Door",None))
            QtWidgets.QApplication.processEvents()
            return GPIO.output(Outer,GPIO.LOW) #Open Outer Door
        elif GPIO.input(Outer) == 0: #OuterDoor Open
            self.ui.InnerSwitch.setEnabled(False)
            self.ui.OuterSwitch.setText(QtWidgets.QApplication.translate("MainWindow", "Open Outer Door",None))
            QtWidgets.QApplication.processEvents()

            QtCore.QTimer.singleShot(3000,partial(self.ui.InnerSwitch.setEnabled,True))
            return GPIO.output(Outer,GPIO.HIGH) #Close OuterDoor




    def  InnerControl(self):
        if GPIO.input(Outer)==0: #Outer Open
            return GPIO.output(Inner,GPIO.HIGH), print("Please Close Outer Door")
        elif GPIO.input(Inner) ==1: #Inner Door Close
            self.ui.InnerSwitch.setText(QtWidgets.QApplication.translate("MainWindow", "Close Inner Door",None))
            QtWidgets.QApplication.processEvents()
            return GPIO.output(Inner,GPIO.LOW) #Open Inner
        elif GPIO.input(Inner) ==0:
            self.ui.InnerSwitch.setText(QtWidgets.QApplication.translate("MainWindow", "Open Inner Door",None))
            QtWidgets.QApplication.processEvents()
            return GPIO.output(Inner,GPIO.HIGH) #Close Inner





        #Troubleshoot-comment in
##    sys.excepthook=sys.excepthook
##    def exception_hook(exctype,value,traceback):
##        print(exctype,value,traceback)
##        sys.exit(1)
##    sys.excepthook=exception_hook




if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mySW = ControlMainWindow()
    mySW.show()
    sys.exit(app.exec_())
    MainWindow.show()
    sys.exit(app.exec_())

这是控制外门的代码部分。

def OuterControl(self):
        if GPIO.input(Inner)==0: #InnerDoorOpen
            return GPIO.output(Outer,GPIO.HIGH),print("Please Close Inner Door")
        elif GPIO.input(Outer) ==1: #Outer Door Close
            self.ui.OuterSwitch.setText(QtWidgets.QApplication.translate("MainWindow", "Close Outer Door",None))
            QtWidgets.QApplication.processEvents()
            return GPIO.output(Outer,GPIO.LOW) #Open Outer Door
        elif GPIO.input(Outer) == 0: #OuterDoor Open
            self.ui.InnerSwitch.setEnabled(False)
            self.ui.OuterSwitch.setText(QtWidgets.QApplication.translate("MainWindow", "Open Outer Door",None))
            QtWidgets.QApplication.processEvents()

            QtCore.QTimer.singleShot(3000,partial(self.ui.InnerSwitch.setEnabled,True))
            return GPIO.output(Outer,GPIO.HIGH) #Close OuterDoor

【问题讨论】:

好的,所以我知道 SingleShot 计时器无法重置,因为它们没有分配给任何东西,但我确信必须有另一种方法。有人可以帮忙吗? 【参考方案1】:

试试看QTimeLine 类提供了用于控制动画的时间线。

import sys
from PyQt5.QtCore    import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui     import *

class Window(QWidget):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        self.resize(400, 230)
        self.setWindowTitle("QTimer.singleShot vs. QTimeLine")

        layV = QVBoxLayout()
        self.setLayout(layV)
        self.lcd = QLCDNumber()  
        self.i = 0        
        layH = QHBoxLayout()
        self.lblSingleShot = QLabel("QTimer.singleShot")
        self.lblSingleShot.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.lblTimeLine   = QLabel("QTimeLine")
        self.lblTimeLine.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        layH.addWidget(self.lblSingleShot)
        layH.addWidget(self.lblTimeLine)

        self.btnStart = QPushButton("Start Timer", clicked=self.startTimer)

        layV.addWidget(self.lcd)
        layV.addLayout(layH)
        layV.addWidget(self.btnStart)

        self.timer = QTimer()  
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.updateData)        

        self.timeLine = QTimeLine(3000)                       # <---
        self.timeLine.setFrameRange(0, 2)  
        self.timeLine.setUpdateInterval(1000)
        self.timeLine.finished.connect(self.finishTimeLine)   # <---

    def finishTimeLine(self):                                 # <---
        self.lblTimeLine.setStyleSheet("background-color: green; color: white;") 

    def startTimer(self):
        if self.btnStart.text() == "Start Timer":
            self.i = 1
            self.lcd.display(self.i)
            self.timer.start(1000) 
            self.btnStart.setText("Stop Timer")
            QTimer.singleShot(3000, self.onShow)
            self.lblSingleShot.setStyleSheet("background-color: white; color: black;")
            self.lblSingleShot.setText("QTimer.singleShot")
            self.lblTimeLine.setStyleSheet("background-color: white; color: black;")
            self.lblTimeLine.setText("QTimeLine")

            self.timeLine.start()                             # <---
        else:
            self.btnStart.setText("Start Timer")
            self.timer.stop()
            self.timeLine.stop()                              # <---
            self.lblTimeLine.setStyleSheet("background-color: red; color: white;")
            self.lblTimeLine.setText("QTimeLine - Stop")
        self.i = 1            

    def updateData(self):
        self.i += 1
        self.lcd.display(self.i)

    def onShow(self):
        self.lblSingleShot.setStyleSheet("background-color: green; color: white;")    
        self.lblSingleShot.setText("<b>def onShow() - Start.")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex  = Window()
    ex.show()
    sys.exit(app.exec_())   

【讨论】:

嘿@S.Nick 感谢您的回复,我仍然不太确定如何在我的代码中实现它。我将用我的完整代码更新问题。【参考方案2】:

我设法解决了这个问题: 所以我所做的是创建一个单独的计时器,可以将其杀死并将其设置为单发。然后我设置了一个可调用函数,它可以将内部开关设置为真/活动。仅当计时器到时.. 见附件代码:

class ControlMainWindow(QtWidgets.QMainWindow):
    def __init__(self,parent=None):
        super(ControlMainWindow,self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.OuterSwitch.clicked.connect(self.OuterControl)
        self.ui.InnerSwitch.clicked.connect(self.InnerControl)

        self.current_timer = None

    def starttimer(self):
        if self.current_timer:
            self.current_timer.stop()
            self.current_timer.deleteLater()
        self.current_timer=QtCore.QTimer()
        self.current_timer.setSingleShot(True)
        self.current_timer.start(3000)
        self.current_timer.timeout.connect(self.InnerSwitchOn)

    def InnerSwitchOn(self):   
        self.ui.InnerSwitch.setEnabled(True)

    def OuterControl(self):
        if GPIO.input(Inner)==0: #InnerDoorOpen
            return GPIO.output(Outer,GPIO.HIGH),print("Please Close Inner Door")
        elif GPIO.input(Outer) ==1: #Outer Door Close
            self.ui.OuterSwitch.setText(QtWidgets.QApplication.translate("MainWindow", "Close Outer Door",None))
            QtWidgets.QApplication.processEvents()
            return GPIO.output(Outer,GPIO.LOW) #Open Outer Door
        elif GPIO.input(Outer) == 0: #OuterDoor Open
            self.ui.InnerSwitch.setEnabled(False)
            self.ui.OuterSwitch.setText(QtWidgets.QApplication.translate("MainWindow", "Open Outer Door",None))
            QtWidgets.QApplication.processEvents()
            self.starttimer()
            return GPIO.output(Outer,GPIO.HIGH) #Close OuterDoor

【讨论】:

以上是关于每当单击按钮时如何重置计时器的主要内容,如果未能解决你的问题,请参考以下文章

重置后JavaScript倒计时器不显示按钮

在 Unity 中使用按钮重置计时器

如何通过单击按钮启动倒数计时器事件?

我如何制作一个可重置的RxSwift计时器?

如何在 qt creator 的 main.cpp 中有一个计时器,以便在单击按钮时更新 GUI?

在 React 中单击按钮时停止计时器