在输入时更改Python Tkinter标签指定的字符字体颜色

问题描述 投票:0回答:1

我想创建像“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 """使炭变绿""" 别的: “”“将炭变成红色”“”

我正在寻找迭代解决方案,但我发现我们无法迭代标签..?

python tkinter iteration
1个回答
0
投票

正如您问题的评论中所提到的,标签元素不提供为其内容的单个单词或字符设置样式的功能。 但是,文本元素可以!

我已经为您的小程序编写了一种面向对象的方法。当使用 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()
© www.soinside.com 2019 - 2024. All rights reserved.