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()
假设我有两个函数,调用它们会打开一个框架:
例如:
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()