3

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コードのみを使用しています。

4

3 に答える 3

3

スレッド化やタイマー/シグナルを使用せずに、ループ内でキーが押されるのを待機しようとすると、ループがブロックされます。

キーが押されるのを待っている間、メインループの処理を続行する(ストップウォッチ)1つの方法は、スレッドを使用することです。このスレッドから解決策を見つけましたが、予備検索でActiveStateレシピにたどり着きました。

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()
于 2013-01-18T15:14:24.077 に答える
1

ストップウォッチ用の 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()
于 2013-01-18T17:38:37.553 に答える
1

呪いを使う:

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 では、モジュールで使用できるため、これは問題ではkbhitありません。getchmsvcrt

于 2013-01-18T20:01:27.627 に答える