最近想写一个类似于自动化模拟考试的东东,其中有一部分是设置倒计时,时间到则停止答题。每个单元分开实现,最后组装在一起就ok 啦,(分开实现,便于调试啦,个人觉得)。花了一个多小时设计和写code,一个多小时debug。嘿嘿。。。
实现平台:Pycharm 3.4.1 python2.7.8 Qt4.8 pyside
王道先行:(声明这只是一个demo,只是实现倒计时器的显示,其余忽略),用的主要控件是QtGui.QLCDNumber
初始界面:
菜单栏:(1)Set CountDown :设置倒计时的时间(1~100)
(2)Start Testing:开始考试,即开始倒计时
(3)Pause Testing:按一下暂停计时,再按一下继续计时,跟音乐播放器的暂停键一样
(4)Stop Testing:中途停止考试,倒计时清0
下面贴代码,就着代码写思路。
from PySide import QtGui,QtCore ORIGINAL_TIME = 0 class MainWindow(QtGui.QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.time = ORIGINAL_TIME self.timer = None self.isPause = False self.creatMenuBar() self.creatToolBar() self.creatActions() self.creatCountDown() self.resize(300,400) def creatMenuBar(self): menuBar = self.menuBar() self.fileMenu = menuBar.addMenu('File') self.setMenuBar(menuBar) def creatToolBar(self): pass def creatActions(self): self.setCountDown = QtGui.QAction('Set CountDown',self,triggered = self.changeCountDown) self.changeBackGround = QtGui.QAction('Change BackGround',self,triggered = self.setBackGround) self.startTesting = QtGui.QAction('Start Testing',self,triggered = self.startTestSet) self.closeTesting = QtGui.QAction('Stop Testing',self,triggered = self.stopTest) self.pauseTesting = QtGui.QAction('Pause Testing',self,triggered = self.pauseTest) self.fileMenu.addAction(self.setCountDown) self.fileMenu.addAction(self.changeBackGround) self.fileMenu.addAction(self.startTesting) self.fileMenu.addAction(self.pauseTesting) self.fileMenu.addAction(self.closeTesting) def changeCountDown(self): #创建倒计时控件 if self.timer is None: self.time,ok = QtGui.QInputDialog.getInteger(self, "Set CountDown", "Percentage:", 45, 0, 120, 1) #获取输入的对话框,这里的45,是在对话框中的已设值 if ok : if self.time <= 0 or self.time > 100: QtGui.QMessageBox.warning(self,"Warning Message",' Please enter a integer i like :0 < i <= 100') self.changeCountDown() #这边有个递归的感觉,如果输入的值不符合要求,则出现提示对话框后,再次出现输入的对话框 else: self.updateTime() #设置完初始值后,更新界面上的显示时间 else: QtGui.QMessageBox.warning(self,"Warning Message"," Please stop the Testing first before you reset the CountDown")
#如果在倒计时的过程中需要重设初始值,则提示“请在重设倒计时前,先停止考试” def updateTime(self): zero = '' zeroDouble = ':00' if self.time < 10: zero = '0' if self.time == 100: zeroDouble = ':0' self.countDown.display(zero + str(self.time)+zeroDouble) def setBackGround(self): pass def startTestSet(self): #这是一个开始到倒计时的模块
self.isPause = False #2014年10月6日添加。。。 if self.timer: self.timer.stop() zero = '' zeroDouble = ':00' if self.time < 10: zero = '0' if self.time == 100: zeroDouble = ':0' self.countDown.display(zero+ str(self.time) +zeroDouble) if self.getNumber(): self.timer = QtCore.QTimer(self) self.timer.timeout.connect(self.timeReset) #每个一秒钟,改变显示的剩余时间 self.timer.start(1000) def getNumber(self): self.minNumber = self.time self.secondNumber = 0 if self.minNumber == 0: QtGui.QMessageBox.warning(self,"Warning Message", " Please set CountDown first!") return False return True def timeReset(self): self.zeroMin = '' self.zeroSecond = '' if self.secondNumber == 0: self.secondNumber = 59 if self.minNumber == 0: #当分钟位和秒钟位同时为0时,表明时间已到,则停止考试,显示提示对话框 self.stopTest() QtGui.QMessageBox.warning(self,"Warning Message", " GAME OVER! Please wait for your record. ") return else: self.minNumber -= 1 else: self.secondNumber -= 1 if self.minNumber < 10: self.zeroMin = '0' if self.secondNumber < 10: self.zeroSecond = '0' self.countDown.display(self.zeroMin + str(self.minNumber) + ':' +self.zeroSecond +str(self.secondNumber)) def stopTest(self): try: self.timer.stop() except: pass self.countDown.display('0'+str(ORIGINAL_TIME) + ":00") self.timer = None self.time = 0 def pauseTest(self): #这个一个暂停计时的模块 if self.timer : if self.isPause: #由于第一次按下暂停键为暂停,第二按下暂停键为继续,故需要一个flag:self.isPause,来随时改变状态 self.isPause = False else: self.isPause = True if self.isPause: self.timer.stop() self.countDown.display(self.zeroMin + str(self.minNumber) + ':' +self.zeroSecond +str(self.secondNumber)) else: self.timer = QtCore.QTimer(self) self.timer.timeout.connect(self.timeReset) self.timer.start(1000) else: return def creatCountDown(self): self.countDown = QtGui.QLCDNumber() self.countDown.display('0'+str(self.time)+":00") self.edit = QtGui.QTextEdit() self.label = QtGui.QLabel('Count Down') #self.label. self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical) splitterH = QtGui.QSplitter() splitterH.addWidget(self.label) splitterH.addWidget(self.countDown) self.splitter.addWidget(splitterH) self.splitter.addWidget(self.edit) self.setCentralWidget(self.splitter) if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) mainWindow = MainWindow() mainWindow.show() sys.exit(app.exec_())
几点注意的地方:
正常的设计案件顺序是:setCountDown——startTesting——(Pause/stop)
但是有些时候肯定会出现乱按键的情况:
(1)还没有设置初始值,就start Testing,所以需要给self.timer在init中赋初值none,并且在start Testing中判断timer是否已经开启,如果没有开启则选获取实现设好的值。如果已开启,则停止timer,并在界面上显示预先设置的初值。重新开始倒计时。
(2)最重要的是在stop 中一定将timer 关掉和将self.time置零。
(3)只要你的timer在运转中,想要重置初值,都会提示:“请先结束考试,再设初值”。
(4)其实,不管键再乱按,只要每个键触犯的函数做好判断就ok啦
不足的地方:
(1)这个LCDNumber模块有个缺点就是只能显示五位,所以去除掉“:”,就只剩下四位,再去掉秒钟位的两位,只能显示的最大值就是99分钟了。。。。
(2)不是很好看呀,哈哈。。还有其他功能上的待发现。
10月6日
今天又发现一个bug,在start---pause---start之后再按pause就不听使唤了(其实是再开启了一个计时器,加快计时了)
原因是:在初始化中将self.isPaused设置为Faulse,然后按下paused键后就将状态倒置为true,在start时,pause的状态还是True,则不会进行暂停。
解决方案:其实只要在每次start时,只要再次对isPause(无条件)初始化为False即可。。。(注意以后也要及时的初始化)