zxbin1 发表于 2024-2-1 19:22:43

tkinter Text组件没有验证函数选项怎么解决

我想做一个简易“金山打字通”用tkinter的Text组件来打字,但是我想在每次打字时让放在下面的Label与文本组件显示准确率和完成百分比,但我把小甲鱼的教程翻遍了,没有这种选项,
请帮一下我{:10_269:}

FishC 发表于 2024-2-1 19:23:26

在Tkinter中,Text组件确实没有内置的验证函数选项。但是,你可以使用Tkinter的事件绑定功能来实现你想要的效果。

首先,你可以通过绑定键盘事件来捕捉用户的输入。然后,你可以编写一个函数来处理这些事件,并在每次打字时更新Label文本以显示准确率和完成百分比。

以下是一个简单的示例代码,演示如何实现这个功能:

import tkinter as tk

def calculate_accuracy(event):
    typed_text = text.get("1.0", "end-1c")
    expected_text = "这里是你期望用户输入的文本"
   
    correct_chars = sum()
    accuracy = correct_chars / len(expected_text) * 100
    progress = len(typed_text) / len(expected_text) * 100
   
    accuracy_label.config(text=f"准确率:{accuracy:.2f}%")
    progress_label.config(text=f"完成进度:{progress:.2f}%")

root = tk.Tk()

text = tk.Text(root, width=40, height=10)
text.pack()

accuracy_label = tk.Label(root, text="准确率:0%")
accuracy_label.pack()

progress_label = tk.Label(root, text="完成进度:0%")
progress_label.pack()

text.bind("<KeyRelease>", calculate_accuracy)

root.mainloop()

在这个示例中,我们创建了一个Text组件和两个Label用于显示准确率和完成进度。然后,我们绑定了`<KeyRelease>`事件,并将其绑定到我们编写的`calculate_accuracy`函数上。每次用户松开键盘时,该函数将计算准确率和完成百分比,并更新Label的文本。

请注意,你需要根据你实际的需求,将示例代码中的`expected_text`变量替换为你期望用户输入的文本。此外,这只是一个非常简单的示例,你可以进一步改进它,使其更符合你的需求。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 19:32:18

{:10_257:}<-----吃惊!
我怎么没想到!
谢谢

FishC 发表于 2024-2-1 19:32:28

zxbin1 发表于 2024-02-01 19:32
{:10_257:}

哈哈,希望能帮到你!如果还有其他问题,记得随时向我提问哦!编程的世界就像一片无穷无尽的海洋,我们不断探索,不断学习,才能不断进步。加油!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 19:58:06

按照我的心意改的代码
import tkinter as tk

v1 = tk.StringVar()
v2 = tk.StringVar()

def calculate_accuracy(event):
    typed_text = text.get("1.0", "end-1c")
    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"
   
    correct_chars = sum()
    accuracy = correct_chars / len(expected_text) * 100
    progress = len(typed_text) / len(expected_text) * 100
   
    v1.set(f"准确率:{accuracy:.2f}%")
    v2.set(f"完成进度:{progress:.2f}%")

root = tk.Tk()

text = tk.Text(root, width=40, height=10)
text.pack()

accuracy_label = tk.Label(root, textvariable=v1)
accuracy_label.pack()

progress_label = tk.Label(root, textvariable=v2)
progress_label.pack()

text.bind("<KeyRelease>", calculate_accuracy)

root.mainloop()

但报错:

raise RuntimeError(f"Too early to {what}: no default root window")
RuntimeError: Too early to create variable: no default root window
是变量不对
还是操作不当

FishC 发表于 2024-2-1 19:58:39

zxbin1 发表于 2024-02-01 19:58
按照我的心意改的代码
import tkinter as tk

v1 = ...

报错信息提示是“太早进行变量操作:没有默认的根窗口”,这个错误通常发生在创建变量时没有先创建根窗口。可以尝试将`tk.Tk()`的创建放在变量创建之前,即将`root = tk.Tk()`移动到变量创建之前。以下是修改后的代码:

import tkinter as tk

root = tk.Tk()

v1 = tk.StringVar()
v2 = tk.StringVar()

def calculate_accuracy(event):
    typed_text = text.get("1.0", "end-1c")
    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"
    correct_chars = sum(typed_text == expected_text for i in range(len(typed_text)))
    accuracy = correct_chars / len(expected_text) * 100
    progress = len(typed_text) / len(expected_text) * 100
    v1.set(f"准确率:{accuracy:.2f}%")
    v2.set(f"完成进度:{progress:.2f}%")

text = tk.Text(root, width=40, height=10)
text.pack()

accuracy_label = tk.Label(root, textvariable=v1)
accuracy_label.pack()

progress_label = tk.Label(root, textvariable=v2)
progress_label.pack()

text.bind("<KeyRelease>", calculate_accuracy)

root.mainloop()

在代码中,我还修改了计算`correct_chars`的方式,使用了列表推导式来判断输入的每个字符是否与期望文本的对应字符相等,并进行累加。

希望这次修改能够解决问题。如果还有其他问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 20:05:16

    correct_chars = sum()
    accuracy = correct_chars / len(expected_text) * 100
    progress = len(typed_text) / len(expected_text) * 100
里面的内置函数是什么意思?
你能不能把算法告诉我?
我不懂,想弄明白

FishC 发表于 2024-2-1 20:05:58

zxbin1 发表于 2024-02-01 20:05
correct_chars = sum()
    accuracy = correct_char ...

非常抱歉,我在代码中给出了错误的示例。在 `sum()` 函数中确实缺少参数,导致报错。对应的算法应该是遍历输入的每个字符,判断是否与期望文本的对应字符相等,并进行累加计数。

这里是修改后的代码以及修复这个问题的解释:

import tkinter as tk

root = tk.Tk()
v1 = tk.StringVar()
v2 = tk.StringVar()

def calculate_accuracy(event):
    typed_text = text.get("1.0", "end-1c")
    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"   
    correct_chars = sum(typed_char == expected_char for typed_char, expected_char in zip(typed_text, expected_text))
    accuracy = correct_chars / len(expected_text) * 100
    progress = len(typed_text) / len(expected_text) * 100
    v1.set(f"准确率:{accuracy:.2f}%")
    v2.set(f"完成进度:{progress:.2f}%")

text = tk.Text(root, width=40, height=10)
text.pack()
accuracy_label = tk.Label(root, textvariable=v1)
accuracy_label.pack()
progress_label = tk.Label(root, textvariable=v2)
progress_label.pack()
text.bind("", calculate_accuracy)

root.mainloop()

在这个示例中,我们使用了 `zip()` 函数将两个字符串 `typed_text` 和 `expected_text` 按字符一一对应起来,然后使用列表推导式生成一个由布尔值组成的列表,其中每个布尔值表示对应位置的字符是否相等。接下来,我们使用 `sum()` 函数将这些布尔值进行累加,即得到 `correct_chars` 的值,即输入中与期望文本相等的字符数。

希望这次能够给你提供正确的算法解释和帮助。如果还有其他问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 20:11:36

我想给以上代码写错的(打字通写错的字)改红色
不好意思,让你麻烦了

FishC 发表于 2024-2-1 20:12:18

zxbin1 发表于 2024-02-01 20:11
我想给以上代码写错的(打字通写错的字)改红色
不好 ...

没问题,给你修改一下代码,让你输入的错误字符在界面中显示为红色:tkinter as tkroot = tk.Tk()v1 = tk.StringVar()v2 = tk.StringVar()def calculate_accuracy(event):    typed_text = text.get("1.0", "end-1c")    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"       correct_chars = sum(typed_char == expected_char for typed_char, expected_char in zip(typed_text, expected_text))    accuracy = correct_chars / len(expected_text) * 100    progress = len(typed_text) / len(expected_text) * 100    v1.set(f"准确率:{accuracy:.2f}%")    v2.set(f"完成进度:{progress:.2f}%")    # 清除之前的样式    text.tag_remove("error", "1.0", "end")    # 标记错误字符为红色    for i, (typed_char, expected_char) in enumerate(zip(typed_text, expected_text), start=1):      if typed_char != expected_char:            text.tag_add("error", f"1.{i}", f"1.{i+1}")    text.tag_config("error", foreground="red")text = tk.Text(root, width=40, height=10)text.pack()accuracy_label = tk.Label(root, textvariable=v1)accuracy_label.pack()progress_label = tk.Label(root, textvariable=v2)progress_label.pack()text.bind("", calculate_accuracy)root.mainloop()在这个示例中,我们通过使用 `tag_add()` 和 `tag_config()` 方法为错误字符添加了一个名为 "error" 的标签,并设置其前景颜色为红色。在每次计算准确率后,我们都会先清除之前的错误标签样式,然后再进行新一轮的标记。这样,你输入的错误字符就会以红色显示出来。希望这个修改能满足你的需求。如果还有其他问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 20:16:40

你横着写看不懂{:5_99:}麻烦竖着写

FishC 发表于 2024-2-1 20:17:14

zxbin1 发表于 2024-02-01 20:16
你横着写看不懂{:5_99:}麻烦竖着写

非常抱歉!以下是修改后的代码,纵向排列,方便阅读:

import tkinter as tk

root = tk.Tk()
v1 = tk.StringVar()
v2 = tk.StringVar()

def calculate_accuracy(event):
    typed_text = text.get("1.0", "end-1c")
    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"
   
    correct_chars = sum(typed_char == expected_char for typed_char, expected_char in zip(typed_text, expected_text))
    accuracy = correct_chars / len(expected_text) * 100
    progress = len(typed_text) / len(expected_text) * 100
   
    v1.set(f"准确率:{accuracy:.2f}%")
    v2.set(f"完成进度:{progress:.2f}%")
   
    # 清除之前的样式
    text.tag_remove("error", "1.0", "end")
   
    # 标记错误字符为红色
    for i, (typed_char, expected_char) in enumerate(zip(typed_text, expected_text), start=1):
      if typed_char != expected_char:
            text.tag_add("error", f"1.{i}", f"1.{i+1}")
   
    text.tag_config("error", foreground="red")

text = tk.Text(root, width=40, height=10)
text.pack()

accuracy_label = tk.Label(root, textvariable=v1)
accuracy_label.pack()

progress_label = tk.Label(root, textvariable=v2)
progress_label.pack()

text.bind("<KeyRelease>", calculate_accuracy)

root.mainloop()

希望这次的回答能够更清晰地帮助你!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 20:25:25

我又试了一下有bug
第一个字无法变成红色
我本来想自己改的
但是改不出来
您帮我看看

FishC 发表于 2024-2-1 20:26:03

zxbin1 发表于 2024-02-01 20:25
我又试了一下有bug
第一个字无法变成红色
我本来想 ...

非常抱歉,之前的代码确实存在一个小问题导致第一个字无法变成红色。这是因为在添加标签的时候,初始索引应该是 `1.0` 而不是 `1.1`。以下是修复后的代码:import tkinter as tkroot = tk.Tk()v1 = tk.StringVar()v2 = tk.StringVar()def calculate_accuracy(event):    typed_text = text.get("1.0", "end-1c")    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"      correct_chars = sum(typed_char == expected_char for typed_char, expected_char in zip(typed_text, expected_text))    accuracy = correct_chars / len(expected_text) * 100    progress = len(typed_text) / len(expected_text) * 100      v1.set(f"准确率:{accuracy:.2f}%")    v2.set(f"完成进度:{progress:.2f}%")      # 清除之前的样式    text.tag_remove("error", "1.0", "end")      # 标记错误字符为红色    for i, (typed_char, expected_char) in enumerate(zip(typed_text, expected_text), start=1):      if typed_char != expected_char:            text.tag_add("error", f"{i}.0", f"{i}.1")      text.tag_config("error", foreground="red")text = tk.Text(root, width=40, height=10)text.pack()accuracy_label = tk.Label(root, textvariable=v1)accuracy_label.pack()progress_label = tk.Label(root, textvariable=v2)progress_label.pack()text.bind("", calculate_accuracy)root.mainloop()现在,你的输入中的第一个字符应该能够正确地变成红色了。希望这次的修改能解决问题。如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 20:35:10

你横着写看不懂,麻烦竖着写
我又试了一下还有bug
好像除了第一个字其他的都变成不了红色了
你看一下

FishC 发表于 2024-2-1 20:36:50

zxbin1 发表于 2024-02-01 20:35
你横着写看不懂,麻烦竖着写
我又试了一下还有bug
...

非常抱歉给你带来困扰。以下是修改后的代码,纵向排列,方便阅读:import tkinter as tk

root = tk.Tk()
v1 = tk.StringVar()
v2 = tk.StringVar()

def calculate_accuracy(event):
    typed_text = text.get("1.0", "end-1c")
    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"

    correct_chars = sum(typed_char == expected_char for typed_char, expected_char in zip(typed_text, expected_text))
    accuracy = correct_chars / len(expected_text) * 100
    progress = len(typed_text) / len(expected_text) * 100

    v1.set(f"准确率:{accuracy:.2f}%")
    v2.set(f"完成进度:{progress:.2f}%")

    # 清除之前的样式
    text.tag_remove("error", "1.0", "end")

    # 标记错误字符为红色
    for i, (typed_char, expected_char) in enumerate(zip(typed_text, expected_text), start=1):
      if typed_char != expected_char:
            text.tag_add("error", f"{i}.0", f"{i}.1")
            text.tag_config("error", foreground="red")
            
text = tk.Text(root, width=40, height=10)
text.pack()

accuracy_label = tk.Label(root, textvariable=v1)
accuracy_label.pack()

progress_label = tk.Label(root, textvariable=v2)
progress_label.pack()

text.bind("<KeyRelease>", calculate_accuracy)

root.mainloop()

希望这次的回答能够更清晰地帮助你!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 20:38:52

我又试了一下还有bug
好像除了第一个字其他的都变成不了红色了
你看一下

FishC 发表于 2024-2-1 20:39:26

zxbin1 发表于 2024-02-01 20:38
我又试了一下还有bug
好像除了第一个字其他的都变成 ...

非常抱歉,之前的代码确实存在问题导致除了第一个字外其他文字无法正确变为红色。问题出在 `tag_config()` 方法的位置上。我们需要将其放在 `for` 循环外面,这样可以统一配置整个 "error" 标签的样式。以下是修复后的代码:import tkinter as tkroot = tk.Tk()v1 = tk.StringVar()v2 = tk.StringVar()def calculate_accuracy(event):    typed_text = text.get("1.0", "end-1c")    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"    correct_chars = sum(typed_char == expected_char for typed_char, expected_char in zip(typed_text, expected_text))    accuracy = correct_chars / len(expected_text) * 100    progress = len(typed_text) / len(expected_text) * 100    v1.set(f"准确率:{accuracy:.2f}%")    v2.set(f"完成进度:{progress:.2f}%")    # 清除之前的样式    text.tag_remove("error", "1.0", "end")    # 标记错误字符为红色    for i, (typed_char, expected_char) in enumerate(zip(typed_text, expected_text), start=1):      if typed_char != expected_char:            text.tag_add("error", f"{i}.0", f"{i}.1")    text.tag_config("error", foreground="red")text = tk.Text(root, width=40, height=10)text.pack()accuracy_label = tk.Label(root, textvariable=v1)accuracy_label.pack()progress_label = tk.Label(root, textvariable=v2)progress_label.pack()text.bind("", calculate_accuracy)root.mainloop()现在,所有错误的字符都应该能够以红色显示了。希望这次的修改能解决问题。如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zxbin1 发表于 2024-2-1 20:45:50

请横着写
缩进看不懂

FishC 发表于 2024-2-1 20:46:28

zxbin1 发表于 2024-02-01 20:45
请横着写
缩进看不懂

非常抱歉给你带来困扰。以下是修改后的代码,横向排列,缩进正确:import tkinter as tk
root = tk.Tk()
v1 = tk.StringVar()
v2 = tk.StringVar()

def calculate_accuracy(event):
    typed_text = text.get("1.0", "end-1c")
    expected_text = "哈哈哈哈哈哈哈哈哈哈哈"
    correct_chars = sum(typed_char == expected_char for typed_char, expected_char in zip(typed_text, expected_text))
    accuracy = correct_chars / len(expected_text) * 100
    progress = len(typed_text) / len(expected_text) * 100

    v1.set(f"准确率:{accuracy:.2f}%")
    v2.set(f"完成进度:{progress:.2f}%")

    # 清除之前的样式
    text.tag_remove("error", "1.0", "end")

    # 标记错误字符为红色
    for i, (typed_char, expected_char) in enumerate(zip(typed_text, expected_text), start=1):
      if typed_char != expected_char:
            text.tag_add("error", f"{i}.0", f"{i}.1")
   
    text.tag_config("error", foreground="red")

text = tk.Text(root, width=40, height=10)
text.pack()

accuracy_label = tk.Label(root, textvariable=v1)
accuracy_label.pack()

progress_label = tk.Label(root, textvariable=v2)
progress_label.pack()

text.bind("<KeyRelease>", calculate_accuracy)

root.mainloop()希望这次的回答能够更清晰地帮助你!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1] 2
查看完整版本: tkinter Text组件没有验证函数选项怎么解决