我想创建像“monkeytype.com”这样的类型测试应用程序 我坚持改变正确或不正确的角色颜色
如果插入的键==字符串中的字符那么我想改变颜色...
# Return a single random word
from random_word import RandomWords
words = []
for i in range(100):
words.append(RandomWords().get_random_word())
"""set tkinter"""
from tkinter import *
win = Tk()
"""centering window"""
window_height = 900
window_width = 1200
screen_width = win.winfo_screenwidth()
screen_height = win.winfo_screenheight()
x_cordinate = int((screen_width/2) - (window_width/2))
y_cordinate = int((screen_height/2) - (window_height/2))
win.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
"""set and start timer when keypress"""
def timeout_message():
popup = Toplevel()
popup.title("Timeout")
popup.geometry("{}x{}+{}+{}".format(300, 100, x_cordinate+450, y_cordinate+400))
popup_label = Label(popup, text="Time's up!", font=("Arial", 20))
popup_label.pack()
popup.focus_set()
"""start_function"""
"""check if char equals string char"""
points = 0
def start():
"""display text"""
start_button.pack_forget()
tekst = Label(text=words,wraplength=1200,font=("Arial",30)).pack()
win.after(30000,timeout_message)
"""Read keypress if key equals char in words then make this char green and iterate through"""
"""Transform words to one string with spaces !!!"""
words_string = ' '.join(words)
wait_var = BooleanVar()
def check_char(event):
global points
char = event.char
wait_var.set(True)
if char == i:
points = points + 1
"""Make char green"""
else:
"""Make char red"""
for i in words_string:
win.bind("<Key>", check_char)
wait_var.set(False)
win.wait_variable(wait_var)
"""bind start button"""
start_button = Button(text="Start", font=("Arial",30),command=start)
start_button.pack()
win.mainloop()
def check_char(事件):
全球点
字符=事件.字符
wait_var.set(True)
如果字符==我:
积分 = 积分 + 1
"""使炭变绿"""
别的:
“”“将炭变成红色”“”
我正在寻找迭代解决方案,但我发现我们无法迭代标签..?
正如您问题的评论中所提到的,标签元素不提供为其内容的单个单词或字符设置样式的功能。 但是,文本元素可以!
我已经为您的小程序编写了一种面向对象的方法。当使用 Tkinter 等类时,如果您也使用基于类的方法,它会更有组织性并且更容易理解。
from tkinter import Tk, Toplevel, Label, Text, Button, messagebox, BooleanVar
from random_words import RandomWords
from datetime import datetime
class App(Tk): # Class inherits from Tk instead of instanciating Tk as win
window_height = 900
window_width = 1200
def __init__(self): # init is calle whenever the class is instanciated
super().__init__() # we have to call the init of Tk as well as we inherit from it
self.rw = RandomWords()
self.words = self.rw.random_words(count=100) # no need for loop to create wordlist
self.points = 0
self.words_string = ' '.join(self.words) # display text
self.wait_var = BooleanVar()
# calculate screen center and place Window
self.x_cordinate = int((self.winfo_screenwidth() / 2) - (self.winfo_screenwidth() / 2))
self.y_cordinate = int((self.winfo_screenheight() / 2) - (self.winfo_screenheight() / 2))
self.geometry(f'{App.window_width}x{App.window_height}+{self.x_cordinate}+{self.y_cordinate}')
# instanciate gui elements
self.start_button = Button(self, text="Start", font=("Arial", 30), command=lambda: self.start())
self.start_button.pack()
self.label = Label(self, text='', wraplength=1200, font=("Arial", 20))
self.label.pack()
self.entry = Text(self, state='disabled', font=("Arial", 20))
self.entry.tag_configure('wrong', foreground='red') # label to format fontcolor to red
# your win.after call did not work for my aproach so i simpified it to track a time delta
self.start_time = datetime.now()
self.current_time = datetime.now()
def start(self):
self.start_time = datetime.now()
self.start_button.pack_forget()
self.label['text'] = self.words_string # display text in label created in init
self.entry.pack() # display the entry field created in init
for char in self.words_string:
self.bind("<Key>", lambda event, s_char=char: self.check_char(event, s_char))
self.wait_var.set(False)
self.wait_variable(self.wait_var)
def check_char(self, event, s_char):
self.current_time = datetime.now()
delta = self.current_time - self.start_time
if delta.seconds <= 30: # an entry is only made if the time is not up
self.wait_var.set(True)
self.entry['state'] = 'normal' # entry is enabled so the input can be inserted
if event.char == s_char: # right char increases the score, input is normal
self.points += 1
self.entry.insert('end', event.char)
else: # wrong char is inserted but with 'wrong' label created in init
self.entry.insert('end', event.char, 'wrong')
self.entry['state'] = 'disabled'
else: # instead of an Toplevel instance a simple messagebox does the trick
again = messagebox.askyesno('Time is up!', f'Your time is up!\n\n You have reached {self.points}/'
f'{len(self.words_string)} Points.\n\n'
'Do you want to try again?')
if again: # basically a reload of the app so the words change and enty is empty again
self.destroy()
self.__init__()
else:
self.destroy()
if __name__ == '__main__':
app = App() # instantiate App class instead of Tk
app.mainloop()