首页 > 解决方案 > 生成 Tk 帧时,如何将函数绑定到返回键?

问题描述

我正在尝试将函数 validateSubmit 绑定到 enter 键,以便可以以更快的速度进行测试,但是我无法确定尝试将其绑定到的位置或内容。在底部的主要内容中,我注释掉了我觉得我得到最接近结果的绑定,但是我已经有足够长的时间知道它目前超出了我的知识范围。这个程序是我对 OOP 的尝试。我还从 validateSubmit 收到一个奇怪的错误,但它似乎是由 tkinter 的内部类型转换引起的,并且似乎除了在终端中回显错误之外没有做任何事情。

##########################################################################################
#Imports
import tkinter as tk
from tkinter import ttk
from tkinter import Tk
from random import randint

########################################################################################## 
class Storage():
    def __init__(self):
        self.timeChoice = 0
        self.gameScore = 0
        self.answer = 0
        self.highScore = 0

    def set_timeChoice(self,x):
        self.timeChoice = x

    def set_gameScore(self,x):
        self.gameScore = x

    def set_answer(self,x):
        self.answer = x

    def set_highScore(self,x):
        self.highScore = x

    def save_highScore(self):
        timeChoiceVar = str(self.timeChoice)

        with open('data' + timeChoiceVar + '.txt',mode='w') as file:
            file.write(str(self.highScore))

    def get_highScore(self):
        timeChoiceVar = str(self.timeChoice)

        try:
            with open('data' + timeChoiceVar + '.txt',mode='r') as file:
                self.highScore = file.read()
        except:
            with open('data' + timeChoiceVar + '.txt',mode='w') as file:
                file.write('0')

##########################################################################################   
class AdditionApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self._frame = None
        self.switch_frame(SetTimePage)

    def switch_frame(self, frame_class):
        new_frame = frame_class(self)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.grid(column=0,row=0,sticky=tk.W)

##########################################################################################
class SetTimePage(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)

        self.timeVar = tk.IntVar()
        data.set_timeChoice(60)

        time_frame = ttk.LabelFrame(self,text=' Test Timer Selection ')
        time_frame.grid(column=0,row=0,padx=6,pady=8,sticky='WE')

        radio1 = tk.Radiobutton(time_frame,text='1 Minute',variable=self.timeVar,value=60,command=lambda: data.set_timeChoice(self.timeVar.get()))
        radio1.grid(column=0,row=0,sticky=tk.W)
        radio1.select()

        radio2 = tk.Radiobutton(time_frame,text='2 Minutes',variable=self.timeVar,value=120,command=lambda: data.set_timeChoice(self.timeVar.get()))
        radio2.grid(column=0,row=1,sticky=tk.W)

        radio5 = tk.Radiobutton(time_frame,text='5 Minutes',variable=self.timeVar,value=300,command=lambda: data.set_timeChoice(self.timeVar.get()))
        radio5.grid(column=0,row=2,sticky=tk.W)

        radio10 = tk.Radiobutton(time_frame,text='10 Minutes',variable=self.timeVar,value=600,command=lambda: data.set_timeChoice(self.timeVar.get()))
        radio10.grid(column=0,row=3,sticky=tk.W)

        start_button = ttk.Button(self,text=' Start ',command=lambda: master.switch_frame(TestPage))
        start_button.grid(column=0,row=1,sticky='WE',pady=4)

##########################################################################################
class TestPage(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)        
        self.answer = tk.IntVar()
        self.scoreVar = 0
        data.set_gameScore(0)
        data.get_highScore()

        self.test_frame = tk.Label(self,text=data.timeChoice)
        self.test_frame.grid(column=3,row=0,sticky=tk.N)

        self.score_frame = tk.Label(self,text='Score: %d' % data.gameScore)
        self.score_frame.grid(column=3,row=1,sticky=tk.N)

        self.high_score_frame = tk.Label(self,text='High Score: %s' % data.highScore)
        self.high_score_frame.grid(column=3,row=2,sticky=tk.N)

        self.solve_frame = ttk.LabelFrame(self,text=' Solve: ')
        self.solve_frame.grid(column=0,row=1,columnspan=2,padx=12,sticky=tk.W)

        self.equation_label = tk.Label(self.solve_frame,text='')
        self.equation_label.grid(column=0,row=0,padx=6,sticky=tk.W)

        self.answer_box = ttk.Entry(self.solve_frame,width=2,textvariable=self.answer)
        self.answer_box.grid(column=1,row=0,padx=12,sticky=tk.W)
        self.answer_box.bind('<Return>', self.validateSubmit)

        self.back_button = ttk.Button(self.solve_frame,text=' Back ',command=lambda: master.switch_frame(SetTimePage))
        self.back_button.grid(column=3,row=0,padx=12,sticky=tk.N)

        self.countdown(data.timeChoice)


    def countdown(self, remaining = None):
        if remaining is not None:
            self.remaining = remaining
            self.generateEquation()
        if self.remaining < 0:
            self.test_frame.configure(text=" Time's up! ")
            self.submit_answer.configure(state='disabled')
            self.answer_box.configure(state='disabled')
        else:
            self.test_frame.configure(text="Seconds remaining: %d" % self.remaining)
            self.high_score_frame.configure(text='High Score: %s' % data.highScore)
            self.submit_answer.bind('<Return>', self.validateSubmit)
            self.remaining = self.remaining - 1
            self.after(1000, self.countdown)

    def generateEquation(self): 
        self.x = randint(0,10)
        self.y = randint(0,10)
        self.z = 0
        self.equation_label.configure(text='%d + %d' % (self.x , self.y))
        self.answer_box.delete(0,3)
        self.answer_box.focus()
        self.submit_answer = ttk.Button(self.solve_frame,text=' Submit ',command=self.validateSubmit)
        self.submit_answer.grid(column=2,row=0,padx=12,sticky=tk.E)


    def validateSubmit(self,event=None):
        while self.remaining >= 0:
            self.z = self.answer.get()
            if self.x + self.y == self.z:
                self.scoreVar += 1
                data.set_gameScore(self.scoreVar)
                self.score_frame.configure(text='Score: %d' % data.gameScore)
                self.generateEquation()
                if int(data.highScore) < data.gameScore:
                    data.set_highScore(data.gameScore)
                    data.save_highScore()
            elif self.x + self.y != self.z :
                self.generateEquation()


##########################################################################################
if __name__ == "__main__":
    data = Storage()
    program = AdditionApp()
    program.title(' Addition Test ')
    #program.bind('<Return>', TestPage.validateSubmit)
    program.mainloop()
    data.save_highScore

标签: python-3.xooptkinter

解决方案


如果您希望用户能够在输入答案后按回车而不是按Submit按钮,那么绑定需要在输入小部件上进行,因为这是具有键盘焦点的小部件。

self.answer_box.bind('<Return>', self.validateSubmit)

此外,您需要确保它validateSubmit可以接受event传入的选项。由于您希望将它用于绑定和按钮单击,最简单的方法是使event参数可选:

def validateSubmit(self, event=None):

推荐阅读