Tkinter - 如何绑定按键(不是按钮)来调用函数?

Tkinter - How to bind a key press (not button) to call a function?

假设我有两个函数,调用它们会打开一个框架:

例如:

from tkinter import *
win = Tk()

class MyFrame(Frame):
    def __init__(self, master, **kwargs):
        Frame.__init__(self, master,
        bg='white' ,**kwargs)

def FuncOne():
    frameone = MyFrame(win)
    frameone.pack()

    lbl = Label(frameone, text="ABC", font='"Serif" 247' , width=win.winfo_screenwidth(), height=win.winfo_screenheight())
    lbl.pack(fill=BOTH, expand=True)


def FuncTwo():
    frametwo = MyFrame(win)
    frametwo.pack()

    lbl = Label(frametwo, text="ABC", font='"Serif" 200', width=win.winfo_screenwidth(), height=win.winfo_screenheight())
    lbl.pack()


win.mainloop()

如何调用 FuncOne 和 FuncTwo,每次使用侧箭头键打开一个单独的框架,并在调用 FuncTwo 时销毁 FuncOne 中的框架,反之亦然?

箭头键的绑定如下:

win.bind('<left>', function)
win.bind('<right>', function2) 

至于去掉每一帧,你需要通过某种方式判断是否存在另一帧,如果存在则销毁它。

frameone = None # Initialize it as nothing
frametwo = None # Initialize it as nothing

def FuncOne():
    global frameone, frametwo # make it accessible
    ...
    if frametwo != None:
        # Get rid of frametwo
        frametwo.destroy()
        frametwo = None 
    ...
    frameone.pack()

def FuncTwo():
    global frameone, frametwo # make it accessible
    ...
    if frameone != None:
        # Get rid of frameone
        frameone.destroy()
        frameone= None 
    ...
    frametwo.pack()

基本上,它所做的是将 frameone 和 frametwo 设置为 None。然后,当调用某个函数时,它将 frameone/frametwo 设置为一个框架对象。然后,调用另一个函数时,它看到另一个框架不是none,所以它销毁它并使它成为none。

以下代码提供了 2 个函数,它们将创建 MyFrame class 的实例。在这个函数中,我们将检查列表是否为空 if actual_frame: returns False 当它为空时并创建你的 class 的实例。在此函数的底部,我们将此实例存储在列表 actual_frame 中。如果你 运行 现在另一个函数 if actual_frame: returns True 它将 destroy 这个实例,clear 列表并构建一个新实例.

from tkinter import *
win = Tk()
class MyFrame(Frame):
    def __init__(self, master, **kwargs):
        Frame.__init__(self, master,
        bg='red' ,**kwargs)
actual_frame=[]
def FuncOne(event):
    if actual_frame:
        actual_frame[0].destroy()
        actual_frame.clear()
        
    frameone = MyFrame(win)
    frameone.grid(column=0,row=0)
    lbl = Label(frameone, text="ABC", font='"Serif" 24' , width=10, height=15)
    lbl.pack(side=TOP,fill=BOTH, expand=True)
    
    actual_frame.append(frameone)

def FuncTwo(event):
    if actual_frame:
        actual_frame[0].destroy()
        actual_frame.clear()
    
    frametwo = MyFrame(win)
    frametwo.grid(column=0,row=0)
    lbl = Label(frametwo, text="XYZ", font='"Serif" 20', width=10,height=15)
    lbl.pack(side=TOP, fill=BOTH, expand=True)
    
    actual_frame.append(frametwo)

win.bind('<Left>', FuncOne)
win.bind('<Right>', FuncTwo)

win.mainloop()

更新 在此更新中,我制作了另一个列表,我们存储了您喜欢的所有功能。我们在这里使用的键在经常 itertools.cycle 的帮助下循环浏览列表。我们在新的绑定函数中调用函数列表中下一个或之前的函数。

from tkinter import *
from itertools import cycle

win = Tk()
class MyFrame(Frame):
    def __init__(self, master, **kwargs):
        Frame.__init__(self, master,
        bg='red' ,**kwargs)

my_funcs=[]
actual_frame=[]

def FuncOne():
    if actual_frame:
        actual_frame[0].destroy()
        actual_frame.clear()
        
    frameone = MyFrame(win)
    frameone.grid(column=0,row=0)
    lbl = Label(frameone, text="ABC", font='"Serif" 24' , width=10, height=15)
    lbl.pack(side=TOP,fill=BOTH, expand=True)
    
    actual_frame.append(frameone)

def FuncTwo():
    if actual_frame:
        actual_frame[0].destroy()
        actual_frame.clear()
    
    frametwo = MyFrame(win)
    frametwo.grid(column=0,row=0)
    lbl = Label(frametwo, text="XYZ", font='"Serif" 20', width=10,height=15)
    lbl.pack(side=TOP, fill=BOTH, expand=True)
    
    actual_frame.append(frametwo)

def FuncThree():
    if actual_frame:
        actual_frame[0].destroy()
        actual_frame.clear()
    
    framethree = MyFrame(win)
    framethree.grid(column=0,row=0)
    lbl = Label(framethree, text="DEF", font='"Serif" 20', width=10,height=15)
    lbl.pack(side=TOP, fill=BOTH, expand=True)
    
    actual_frame.append(framethree)
    
my_funcs.append(FuncOne)
my_funcs.append(FuncTwo)
my_funcs.append(FuncThree)

cycle_of_funcs = cycle(my_funcs)

def right_way(event):
    func = next(cycle_of_funcs)
    func()
def left_way(event):
    leng = len(my_funcs)
    for function in range(leng-1):
        func = next(cycle_of_funcs)
    func()
win.bind('<Left>', left_way)
win.bind('<Right>', right_way)

win.mainloop()

我只想在这里发表评论,我认为这不是最好的方法,但仍然是一种可能的方法。只是为了确保这个答案是 space 的 OOP 解决方案 [click]

我做了一个选择器函数,它是一个事件。还有一个帧计数,它告诉选择器应该从哪一个开始。在你的函数开始时,我销毁了另一个 window。这是我的代码:

from tkinter import *
win = Tk()
frame = 1



class MyFrame(Frame):
    def __init__(self, master, **kwargs):
        Frame.__init__(self, master,
        bg='white' ,**kwargs)

def FuncOne():
    global frameone
    try:
        frametwo.destroy()
    except:
        pass

    frameone = MyFrame(win)
    frameone.pack()

    lbl = Label(frameone, text="ABC", font='"Serif" 247' , width=win.winfo_screenwidth(), height=win.winfo_screenheight())
    lbl.pack(fill=BOTH, expand=True)


def FuncTwo():
    global frametwo
    try:
        frameone.destroy()
    except:
        pass

    frametwo = MyFrame(win)
    frametwo.pack()

    lbl = Label(frametwo, text="ABC", font='"Serif" 200', width=win.winfo_screenwidth(), height=win.winfo_screenheight())
    lbl.pack()
def picker(event):
    global frame
    if frame == 1:
        frame = 2
        FuncOne()

    else:
        frame = 1
        FuncTwo()
win.bind('<Left>', picker)
win.bind('<Right>', picker)
win.mainloop()