【发布时间】:2017-09-21 13:19:00
【问题描述】:
总结
在 Python Tkinter 应用程序中,使用 ttk.Notebook 时,如何绑定按键事件,以便它仅在包含生成事件的框架的选项卡处于活动状态时触发(即,对于按钮热键,我如何只在按钮位于活动选项卡上时捕获事件)?
详情
我正在编写一个 Tkinter 应用程序(我的第一个),它使用 ttk.Notebook 对象来管理界面的多个部分。我有多个选项卡,其中一些具有“相同”按钮,但它们具有不同的操作,具体取决于哪个选项卡处于活动状态(即,一个选项卡上的“保存”按钮仅保存来自该选项卡的项目,而不是来自所有标签)。
执行此操作的直观方法是将事件绑定到框架,然后包含“活动”对象的框架将捕获该事件,但这似乎不起作用。但是,如果我将事件绑定到根窗口,则无论选项卡上下文如何,都会调用相同的处理程序。
我认为这是一个常见的要求,但是我无法找到有关如何执行此操作的信息。
我正在使用 Python 3.4.3。
MCVE
这是一个最小示例,它演示了我观察到的行为。它生成一个带有五个选项卡的主窗口,每个选项卡都有一个 Alt-t 的事件绑定,它应该触发该选项卡中框架的事件处理程序。
import tkinter as tk
from tkinter import ttk
class MyTab(ttk.Frame):
"""Frame to be added to each tab of the notebook.
"""
def __init__(self, master, idx, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self._button = ttk.Button(self, text='Tab {}'.format(idx),
command=lambda *args, x=idx: self._handle_button(x, *args),
underline=0)
self.bind('<Alt-t>', lambda *args, x=idx: self._handle_button(x, *args))
self._button.pack()
self.pack()
def _handle_button(self, x, *args):
print('Button: Tab {}'.format(x))
class MainWdw(ttk.Frame):
"""Main application window.
"""
def __init__(self, master, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self._nb = ttk.Notebook(self)
# Generate several tabs and add a MyTab object to each.
self._tabs = []
for x in range(1, 6):
t = MyTab(self, x)
self._tabs.append(t)
self._nb.add(t, text='Tab {}'.format(x))
self._nb.pack(expand=1, fill='both')
master.title('Sample')
self.pack(expand=1, fill='both', padx=2, pady=2)
def main():
root = tk.Tk()
app = MainWdw(root)
root.mainloop()
if __name__ == '__main__':
main()
【问题讨论】:
-
您的代码似乎对我有用。当我按 Alt-t 时,我看到正在打印正确的数字。你是说你看到了不同的行为?
-
是的 - 当我按下 Alt-t 时,我什么也得不到,但是当我点击按钮时,我看到了我期望看到的内容。平台重要吗?在这种情况下,我使用的是 Windows。
-
平台可能很重要。我在ubuntu上测试过,目前无法访问windows机器。
-
这是一个工作项目(将在 Windows 上运行)。我在家里使用 Ubuntu,今晚将测试。你使用的是什么版本的 Python/Tkinter?我想这也可能有所作为。
标签: python python-3.x tkinter ttk