python - OOP,我想在切换帧时取消任何功能
问题描述
因为我使用了 OOP,所以即使没有填充 set 容器,所有帧都已初始化并运行函数。这意味着如果我的游戏正在运行,即使窗口发生变化,它也会继续运行。我想这样做,以便如果显示新框架,所有功能/方法都停止为其他窗口运行。目前,如果游戏开始,倒计时将继续进行,无论显示什么(例如菜单屏幕)。
这是所有窗口继承并排序的类:
class TextTypers(tk.Tk):
def __init__(self, *args, **kwargs): # Runs when our class is called and allows almost anything to be passed
tk.Tk.__init__(self, *args, **kwargs) # Initialise Tk
window = tk.Frame(self) # Creates the container the windows/frames will populate
window.pack(fill="both", expand=True)
self.frames = {} # Creates a dictionary for the frames
for F in (MenuScreen, GameScreen, InstructionsScreen):
frame = F(window, self) # Adds all frames to dictionary so they can be accessed later
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nswe")
self.show_frame(MenuScreen) # Shows the menu screen as this is initialised when the program is run
def show_frame(self, cont):
frame = self.frames[cont] # Grabs value of self.frames and puts in in frame
frame.tkraise() # Raises frame to the front
以下是游戏画面的相关 GUI:
class GameScreen(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent) # Inherits from main class
self.label = tk.ttk.Label(self, text="Type the words as quick as you can!",
font=("arial", 35, "bold"), justify="center")
self.label.grid(row=1, column=3, pady=10, padx=10)
self.time_label = tk.ttk.Label(self, text="Time left: " + str(timer), font=("arial", 30, "bold"),
justify="center")
self.time_label.grid(row=3, column=3, columnspan=2, padx=10, pady=10)
self.word_label = tk.ttk.Label(self, font=("arial", 25, "bold"), justify="center")
self.word_label.grid(row=5, column=3, padx=10, pady=10)
self.entry = tk.DoubleVar()
self.entry.set("")
self.entry = tk.ttk.Entry(self, textvariable=self.entry, font=("arial", 25, "bold"), state='disabled')
self.entry.grid(row=6, column=3)
self.start_button = tk.Button(self, text="Start!", font=("arial", 20, "bold"),
command=self.game, width=10, height=2)
self.start_button.grid(row=7, column=3, pady=10, padx=10)
self.entry.bind('<Return>', self.check_word)
self.home_button = tk.Button(self, text="Home", font=("arial", 20, "bold"),
command=lambda: controller.show_frame(MenuScreen), width=10, height=2)
self.home_button.grid(row=8, column=3, pady=10, padx=10)
def game(self):
global timer
timer = 60
self.entry.config(state="enabled")
self.entry.delete("0", "end")
self.start_button.config(text="Stop", command=lambda: self.stop())
if timer == 60: # Starts the timer and calls the words function
self.countdown()
self.words()
def countdown(self):
global timer
if timer > 0:
timer -= 1
# Update the time left label
self.time_label.config(text="Time left: " + str(timer))
# Run the function again after 1 second
self.time_label.after(1000, self.countdown)
def words(self):
global timer
global word
if timer > 0:
self.entry.focus_set() # Activate the entry box
word = random.choice(word_list[0])
self.word_label.config(text=word)
if timer == 0:
self.results(score)
def check_word(self, event):
global word, score, wrong
entered_word = self.entry.get().lower().strip()
if entered_word == word.lower().strip():
score += 1
else:
wrong += 1
self.words()
self.entry.delete('0', 'end')
def results(self, score):
global top_score
self.entry.config(state='disabled')
if score > top_score:
top_score = score
else:
top_score = top_score
accuracy = score / (score + wrong) * 100
self.word_label.config(
text=f"In one minute you correctly typed {score} words.\n"
f"This is a WPM of {score}, your actual WPM is most likely higher.\n "
f"You got {score} words correct and {wrong} words wrong. \n"
f" That gives you an accuracy of {accuracy:.1f}%!\n"
f"Your top score is {top_score}!", font=("arial", 20, "bold"))
self.start_button = tk.Button(self, text="Play again?", font=("arial", 20, "bold"), command=self.game)
self.start_button.grid(row=7, column=3, pady=10, padx=10)
return top_score
解决方案
您必须在以下位置保留对回调 id 的引用self.countdown()
:
self.current_callback_id = self.time_label.after(1000, self.countdown)
然后调用after_cancel(self.current_callback_id)
换帧。
这可能需要在更改帧逻辑中使用一些机制。
推荐阅读
- c++ - 自动化各种类型的重复代码?
- c# - C# 编写自定义 xmp 元数据
- r - 使用进出时间记录每 15 分钟计数一次客户
- laravel - Laravel 帆。重定向到 docker 教程页面
- javascript - TypeORM 连接映射到 table.relation.id 而不是 table.relationId
- regex - 正则表达式匹配顶级域不是 .com、.net、.org、.info、.edu、.gov 或 .ca 的 url
- python - 当我尝试将其用于大文件时,如何防止此代码崩溃?
- spring-boot - 为什么查询中的 % 运算符不适用于包含数字的字符串?(JPA)
- json - Thingsboard:当时间戳为 ISO 8601 格式时,无法读取有效的 JSON 有效负载
- c# - 为什么 NHibernate 使用 NVARCHAR 而不是 VARCHAR 忽略列类型映射?