Python | How do i make a Fast Reaction test with Tkinter?

眉间皱痕 提交于 2021-02-17 05:34:10

问题


I tried making a fast reaction tester with Tkinter Module in Python, but when I clicked the Start button, it justs freezes the window. And I don't know how to recover that

Here's my code:

import webbrowser as wb
import time
import math
from random import *
from tkinter import *
from PIL import ImageTk, Image

seconds = 0
miliseconds = 0
minutes = 0


def reactionStarted():
    global seconds, miliseconds, greenimages, redimages, minutes
    # Put Image Green
    reactionImage.config(image=greenimages)

    # Random Countdown
    countdownSecond = randint(4, 9)
    countdownMiliSecond = randint(0, 9)

    # Turn into float ( More Randomized )
    countdownBonk = float(str(countdownSecond) + "." + str(countdownMiliSecond))

    # Start Countdown
    print(countdownBonk) # i was testing if this was the problem but its not
    time.sleep(countdownBonk)

    # Red image ( fast reaction part )
    reactionImage.config(image=redimages)

    # Timer
    timeLoop = True
    while timeLoop:

        miliseconds += 1
        time.sleep(0.1)
        if miliseconds == 10:
            seconds += 1
            miliseconds = 0
        elif seconds == 60:
            seconds = 0
            minutes += 1


def reactionCompleted():
    global seconds, miliseconds, minutes
    timeLoop = False
    if not timeLoop:
        reactionImage.config(image='', text=(
                str(minutes) + "Minute(s)" + str(seconds) + "Second(s)" + str(miliseconds) + "Milisecond(s)"))


root = Tk()
root.title("Fast Reaction Test")

greenimages = ImageTk.PhotoImage(Image.open("green.png"))
redimages = ImageTk.PhotoImage(Image.open("red.png"))

reactionImage = Label(text='Click the button Below To Start!')
reactionImage.pack()
Start = Button(root, width=500, height=5, text="Click Here to Start", command=reactionStarted)
Start.pack()
Stop = Button(root, width=500, height=10, text="Stop (Spacebar)", command=reactionCompleted)
Stop.bind("<space>", reactionCompleted)
Stop.focus_force()
Stop.pack()

root.mainloop()

Really, thanks if you helped me out :)


回答1:


Your error is that you are asking your program to enter an infinite loop when clicking the start button. The interpreter never leaves that loop, and thus the UI gets stuck without being able to update itself or receive input, because the interpreter is still stuck within your loop.

So you need to have another approach for this. Issues like these are normally handled by opening separate threads in your program, that can execute independently such that your main thread responsible for updating the UI window is not impacted by the child thread running your infinite loop. Then the main thread can at some point send a message to the child thread that the loop should be cancelled, when you user presses the stop button.

Handling this in tkinter has been made easy with the after() method, which simply put creates such an infinite loop in a separate thread to allow the main thread to keep running. I have below included a small example of how such an after loop can look, and you can try implementing that in your own code. If you still have problems, open a new question with more clarity.

import tkinter as tk
import time


class Timer:
    def __init__(self):
        self.root = tk.Tk()
        self.sv = tk.StringVar()
        self.start_time = None
        self.after_loop = None

        self.make_widgets()
        self.root.mainloop()

    def make_widgets(self):
        tk.Label(self.root, textvariable=self.sv).pack()
        tk.Button(self.root, text='start', command=self.start).pack()
        tk.Button(self.root, text='stop', command=self.stop).pack()

    def start(self):
        self.start_time = time.time()
        self.timer()

    def timer(self):
        self.sv.set(round(time.time() - self.start_time))
        self.after_loop = self.root.after(500, self.timer)

    def stop(self):
        if self.after_loop is not None:
            self.root.after_cancel(self.after_loop)
            self.after_loop = None


Timer()


来源:https://stackoverflow.com/questions/65231089/python-how-do-i-make-a-fast-reaction-test-with-tkinter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!