You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Tkinter打字测速应用运行时,如何实时获取文本框输入值?

解决CTkTextbox实时输入比对问题

问题根源

  • 代码仅在初始化和start_test时各获取一次输入,没有持续监听输入变化,无法实现实时比对
  • tset_user_text仅被调用一次,缺乏循环执行逻辑,无法实时检查用户输入
  • 获取输入时未处理CTkTextbox自带的换行符,可能导致比对偏差

修改方案

  1. 移除__init__中对tset_user_text的调用,改为在测试启动后通过window.after循环触发输入检查
  2. 新增循环检查函数,每次获取当前输入并处理换行符
  3. 调整tset_user_text的统计逻辑,实时更新正确/错误字符数,避免累积错误

修改后的完整代码

def run_test():
    random_number = random.randint(1, 5)
    test = session.query(data).filter(database.Database.id == random_number).first()
    return test


class UserInterFace:

    def __init__(self):
        customtkinter.set_appearance_mode("dark")
        customtkinter.set_default_color_theme("green")
        self.window = CTk()
        self.window.title("Typing Speed Test Application")
        self.window.resizable(False, False)
        self.window.config(padx=50, pady=50)
        self.window.geometry("1000x700")
        self.test = run_test()
        self.wrong_entry = 0
        self.correct_entry = 0
        self.test_running = True
        self.start_count = 5
        self.start_test_btn = None
        self.timer = None
        self.start_test_time = None
        self.end_test_time = None
        self.get_ready_label = CTkLabel(master=self.window,
                                        font=timer_font,
                                        text="Get ready Test will be start in :",
                                        text_color="#609EA2")
        self.count_down_label = CTkLabel(master=self.window,
                                         font=count_down_font,
                                         text=str(self.start_count),
                                         text_color="#820000")
        self.label_test = CTkLabel(master=self.window,
                                   font=my_font2,
                                   text="",
                                   wraplength=900,
                                   )

        self.best_score_record = CTkLabel(master=self.window,
                                          font=my_font1,
                                          text_color="#609EA2",
                                          text="")
        self.type_area = CTkTextbox(master=self.window,
                                    width=900,
                                    height=200)
        self.main()
        self.window.mainloop()

    def start_test(self, test):
        self.start_test_time = time.time()
        self.get_ready_label.grid_forget()
        self.count_down_label.grid_forget()
        test_id = test.id
        test_text = test.text
        test_record = test.record
        self.label_test.configure(text=test_text)
        if test_record == 0:
            test_record = "No Record Yet"
        else:
            test_record = f"Best Record : {test_record}"
        self.best_score_record.configure(text=test_record)
        self.best_score_record.grid(row=0, column=0)
        self.label_test.grid(row=1, column=0, pady=(20, 0))
        self.type_area.grid(row=2, column=0, pady=(20, 0))
        self.type_area.focus_set()
        # 启动实时输入检查循环
        self.check_input_loop()

    def main(self):
        self.start_test_btn = CTkButton(master=self.window,
                                        text="Start Test",
                                        command=lambda: self.start_time(),
                                        height=100,
                                        width=300,
                                        font=my_font1)
        self.start_test_btn.grid(row=0, column=0, padx=(300, 0), pady=(250, 0))

    def start_time(self):
        if self.start_count >= 0:
            self.start_test_btn.grid_forget()
            self.get_ready_label.grid(row=0, column=0, pady=(50, 100), padx=(200, 0))
            self.count_down_label.grid(row=1, column=0, padx=(200, 0))
            self.count_down_label.configure(text=self.start_count)
            self.start_count -= 1
            self.timer = self.window.after(1000, self.start_time)
        else:
            self.window.after_cancel(self.timer)
            self.start_test(self.test)

    def check_input_loop(self):
        if self.test_running:
            # 获取当前输入并去除末尾换行符
            current_input = self.type_area.get("1.0", "end-1c")
            self.tset_user_text(self.test.text, current_input)
            # 每隔100ms再次检查,可根据需求调整间隔
            self.window.after(100, self.check_input_loop)

    def tset_user_text(self, test_text, user_text):
        test_chars = list(test_text)
        user_chars = list(user_text)
        # 重置统计,避免每次检查累积计数
        self.correct_entry = 0
        self.wrong_entry = 0

        # 只比对到两者中较短的长度,防止索引越界
        compare_len = min(len(test_chars), len(user_chars))
        for n in range(compare_len):
            if test_chars[n] == user_chars[n]:
                self.correct_entry += 1
            else:
                self.wrong_entry += 1

        # 检查是否完成输入
        if len(user_chars) >= len(test_chars):
            self.test_running = False
            self.end_test_time = time.time()
            # 可在此添加测试结束后的结果展示逻辑
            print(f"测试完成!正确字符:{self.correct_entry},错误字符:{self.wrong_entry}")

关键修改说明

  • check_input_loop函数:通过window.after循环调用,每隔100ms获取一次当前输入,实现实时监听
  • 使用"end-1c"替代END获取输入,避免把CTkTextbox自动添加的换行符计入输入内容
  • tset_user_text每次检查前重置统计,确保计数是当前输入的实时结果,而非累积值

内容的提问来源于stack exchange,提问作者Pourya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:25:35