Tkinter - как привязать нажатие клавиши (не кнопки) для вызова функции? - PullRequest
0 голосов
/ 02 августа 2020

Предположим, у меня есть две функции, которые при вызове открывают фрейм:

Например:

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, которые каждый раз открывают отдельный фрейм, используя боковую стрелку и уничтожить фрейм в FuncOne при вызове FuncTwo и наоборот?

Ответы [ 3 ]

1 голос
/ 02 августа 2020

Следующий код предоставляет 2 функции, которые создадут экземпляр вашего класса MyFrame. В этой функции мы проверим, пуст ли список, с помощью команды if actual_frame: вернем False, когда он пуст, и создадим экземпляры вашего класса. Внизу этой функции w ie сохраните этот экземпляр в списке actual_frame. Если вы запустите сейчас в другой раз, функция if actual_frame: вернет 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()

Я просто хочу оставить здесь комментарий, который, на мой взгляд, не лучший способ сделать это, но еще возможный способ. Просто чтобы убедиться, что в этом ответе есть место для OOP решений [щелкните]

0 голосов
/ 02 августа 2020

Я сделал функцию выбора, которая является событием. Существует также счетчик кадров, который сообщает сборщику, какой из них следует запускать. В начале вашей функции я уничтожаю другое окно. Вот мой код:

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()
0 голосов
/ 02 августа 2020

Вот привязки клавиш со стрелками:

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 для объекта кадра. Затем, когда вызывается другая функция, она видит, что другой фрейм не является пустым, поэтому уничтожает его и делает его пустым.

...