蟒蛇|如何使用 Tkinter 进行快速反应测试? [英] Python | How do i make a Fast Reaction test with Tkinter?

查看:25
本文介绍了蟒蛇|如何使用 Tkinter 进行快速反应测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用 Python 中的 Tkinter 模块制作一个快速反应测试器,但是当我单击 Start 按钮时,它只是冻结了窗口.我不知道如何恢复

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

这是我的代码:

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 :)

推荐答案

您的错误是您要求程序在单击开始按钮时进入无限循环.解释器永远不会离开那个循环,因此 UI 卡住了,无法更新自身或接收输入,因为解释器仍然卡在你的循环中.

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.

所以你需要另一种方法来解决这个问题.像这样的问题通常是通过在程序中打开单独的线程来处理的,这些线程可以独立执行,这样负责更新 UI 窗口的主线程就不会受到运行无限循环的子线程的影响.然后,当用户按下停止按钮时,主线程可以在某个时候向子线程发送消息,告知应该取消循环.

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.

使用 after() 方法可以轻松地在 tkinter 中处理此问题,该方法只需 put 在单独的线程中创建这样一个无限循环,以允许主线程继续运行.我在下面包含了一个关于这种 after 循环外观的小示例,您可以尝试在自己的代码中实现它.如果您仍有问题,请提出一个更清晰的新问题.

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()

这篇关于蟒蛇|如何使用 Tkinter 进行快速反应测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆