【问题标题】:Python Tkinter call default event handlerPython Tkinter 调用默认事件处理程序
【发布时间】:2018-07-23 16:52:53
【问题描述】:

我有一个带有输入框和按钮的 GUI。当我按“q”时,关闭按钮将被聚焦,除非条目具有焦点。按下“q”时聚焦按钮有效,但是当我想在条目中插入“q”时,它会失去焦点,因此我无法继续在输入框中插入文本。

import tkinter as tk

class Window(tk.Tk):

        def __init__(self):
                tk.Tk.__init__(self)

                self.e = tk.Entry(self)
                self.e.pack()

                f = tk.Frame(self)
                f.pack()

                self.btn_save = tk.Button(f, text="save", command=lambda: print("save"))
                self.btn_save.pack(side='left')

                self.btn_close = tk.Button(f, text="close", command=self.destroy)
                self.btn_close.pack(side='left')

                self.bind('<w>', lambda e: self.btn_save.focus_set())
                self.bind('<q>', lambda e: self.btn_close.focus_set())

                self.e.focus_set()

w = Window()
w.mainloop()

我知道对于自定义事件处理程序,我可以通过返回 'break' 来避免调用更多的事件处理程序。但是如何调用Entry 的事件处理程序呢? 在下面的代码中,在选择条目时,按下“Q”不会重新关注关闭按钮,但我可以在所有内插入任何文本。

import tkinter as tk

class Window(tk.Tk):

        def __init__(self):
                tk.Tk.__init__(self)

                self.e = tk.Entry(self)
                self.e.pack()

                f = tk.Frame(self)
                f.pack()

                self.btn_save = tk.Button(f, text="save", command=lambda: print("save"))
                self.btn_save.pack(side='left')

                self.btn_close = tk.Button(f, text="close", command=self.destroy)
                self.btn_close.pack(side='left')

                self.bind('<w>', lambda e: self.btn_save.focus_set())
                self.bind('<q>', lambda e: self.btn_close.focus_set())

                self.e.bind('<Key>', self.on_key_press)
                self.e.focus_set()

        def on_key_press(self, event):
                # How can I call the default event handler here
                # which takes care of inserting and removing characters, moving the cursor and everything?
                return 'break'

w = Window()
w.mainloop()

(顺便说一句,通过键盘调用关闭按钮时,窗口会按预期关闭,但之后键盘会被忽略,直到我单击另一个窗口。我使用的是 i3 版本 4.8 和 Python 3.4.2。)

【问题讨论】:

  • 如果您执行return 'break',它将不会调用默认处理程序。如果您删除return 'break',它将被调用。这不是你想要的吗?
  • @ritlew 是的,但是它也会调用其他事件处理程序,如果我尝试在输入框中输入“q”,输入框会失去焦点,这不是我想要的。我只希望执行 Entry 的事件处理程序,而不是绑定到根窗口的事件处理程序。

标签: python tkinter


【解决方案1】:

不过,我找到了一个看起来不太优雅的解决方法。 特别是如果您有多个输入框,这似乎不是一个好方法。

在聚焦按钮的事件处理程序中,检查哪个小部件具有焦点,如果是输入框则什么也不做:

import tkinter as tk

class Window(tk.Tk):

        def __init__(self):
                tk.Tk.__init__(self)

                self.e = tk.Entry(self)
                self.e.pack()

                self.frame_buttons = tk.Frame(self)
                self.frame_buttons.pack()

                self.btn_save = tk.Button(self.frame_buttons, text="save", command=lambda:              print("save"))
                self.btn_save.pack(side='left')

                self.btn_close = tk.Button(self.frame_buttons, text="close", command=self.destroy)
                self.btn_close.pack(side='left')

                self.bind('<w>', lambda e: None if self.focus_get() == self.e else self.btn_save.       focus_set())
                self.bind('<q>', lambda e: None if self.focus_get() == self.e else self.btn_close.      focus_set())

                self.e.focus_set()

w = Window()
w.mainloop()

如果有人能找到更好的解决方案,我将不胜感激。


关于通过键盘调用关闭按钮后键盘被忽略的问题,它似乎有助于解压按钮框架并在销毁窗口之前更新窗口:

        def destroy(self):
                self.frame_buttons.pack_forget()
                self.update()
                tk.Tk.destroy(self)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多