【问题标题】:Stopwatch in python? Count until you press spacepython中的秒表?数到按空格键
【发布时间】:2013-01-02 06:35:18
【问题描述】:

我想在 python 3.3 中制作一个秒表,它会继续计数,直到您按下按钮或其他东西,然后它应该停止计数。这是我的代码:

seconds = 0
minutes = 0
continued = 0
while continued != 1:
    print(minutes, ":", seconds)
    time.sleep(1)
    if seconds == 59:
        seconds = 0
        minutes = minutes + 1
    else:
        seconds = seconds + 1

不使用 CTRL + C

我没有使用 GUI 或任何东西,只是使用 IDLE 在命令提示符下运行纯 Python 代码。

【问题讨论】:

  • 那么问题出在哪里?它会一直运行,直到你用 + 杀死它
  • 你反对使用guiTkinter吗?
  • 不使用 gui 或任何东西,使用在命令提示符下运行的 IDLE 的纯 python 代码
  • 什么操作系统?最好使用操作系统计时器,或者简单地使用按键前后的时间差。

标签: python stopwatch


【解决方案1】:

尝试在循环中等待按键,没有线程或计时器/信号将阻塞循环。

在等待按键时让主循环继续处理(秒表)的一种方法是通过线程。初步搜索将我带到了ActiveState recipe,尽管我从this thread 找到了解决方案。

import threading, os, time, itertools, queue

try : # on windows
    from msvcrt import getch
except ImportError : # on unix like systems
    import sys, tty, termios
    def getch() :
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try :
            tty.setraw(fd)
            ch = sys.stdin.read(1)
        finally :
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

commands = queue.Queue(0)

def control(commands) :

    while 1 :

        command = getch()
        commands.put(command) # put the command in the queue so the other thread can read it

        #  don't forget to quit here as well, or you will have memory leaks
        if command == " " :
            print "Stop watch stopped!"
            break

def display(commands):
    seconds = 0
    minutes = 0

    command = ""

    while 1 :

        # parsing the command queue
        try:
           # false means "do not block the thread if the queue is empty"
           # a second parameter can set a millisecond time out
           command = commands.get(False) 
        except queue.Empty, e:
           command = ""

        # behave according to the command
        if command == " " :
            break

        print(minutes, ":", seconds, end="")

        if seconds == 59:
            seconds = 0
            minutes = minutes + 1
        else:
            seconds = seconds + 1
        time.sleep(1)


# start the two threads
displayer = threading.Thread(None,display,None, (commands,),{})

controler = threading.Thread(None, control, None, (commands,), {})

if __name__ == "__main__" :
    displayer.start()
    controler.start()

【讨论】:

    【解决方案2】:

    如果您想要秒表的 GUI,您可能会对以下适用于 Python 3.x 的代码感兴趣。

    #! /usr/bin/env python3
    import tkinter
    import time
    
    class StopWatch(tkinter.Frame):
    
        @classmethod
        def main(cls):
            tkinter.NoDefaultRoot()
            root = tkinter.Tk()
            root.title('Stop Watch')
            root.resizable(True, False)
            root.grid_columnconfigure(0, weight=1)
            padding = dict(padx=5, pady=5)
            widget = StopWatch(root, **padding)
            widget.grid(sticky=tkinter.NSEW, **padding)
            root.mainloop()
    
        def __init__(self, master=None, cnf={}, **kw):
            padding = dict(padx=kw.pop('padx', 5), pady=kw.pop('pady', 5))
            super().__init__(master, cnf, **kw)
            self.grid_columnconfigure(1, weight=1)
            self.grid_rowconfigure(1, weight=1)
            self.__total = 0
            self.__label = tkinter.Label(self, text='Total Time:')
            self.__time = tkinter.StringVar(self, '0.000000')
            self.__display = tkinter.Label(self, textvariable=self.__time)
            self.__button = tkinter.Button(self, text='Start', command=self.__click)
            self.__label.grid(row=0, column=0, sticky=tkinter.E, **padding)
            self.__display.grid(row=0, column=1, sticky=tkinter.EW, **padding)
            self.__button.grid(row=1, column=0, columnspan=2,
                               sticky=tkinter.NSEW, **padding)
    
        def __click(self):
            if self.__button['text'] == 'Start':
                self.__button['text'] = 'Stop'
                self.__start = time.clock()
                self.__counter = self.after_idle(self.__update)
            else:
                self.__button['text'] = 'Start'
                self.after_cancel(self.__counter)
    
        def __update(self):
            now = time.clock()
            diff = now - self.__start
            self.__start = now
            self.__total += diff
            self.__time.set('{:.6f}'.format(self.__total))
            self.__counter = self.after_idle(self.__update)
    
    if __name__ == '__main__':
        StopWatch.main()
    

    【讨论】:

      【解决方案3】:

      使用诅咒:

      import curses
      from datetime import datetime
      
      SPACE_KEY = ord(' ')
      
      def run(win):
          curses.echo()
          win.timeout(1000) # Wait at most one second for a key.
      
          start = datetime.now()
          while True:
              now = datetime.now()
              minutes, seconds = divmod((now - start).total_seconds(), 60)
              win.addstr(0, 0, "%02d:%02d" % (minutes, round(seconds)))
      
              c = win.getch()
              if c == SPACE_KEY:
                  break
      
      curses.wrapper(run)
      

      在 Windows 下,这不是问题,因为 msvcrt 模块中有 kbhitgetch

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-03
        • 2012-11-08
        • 1970-01-01
        • 1970-01-01
        • 2016-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多