Summary
In a Python Tkinter application, when using ttk.Notebook
, how do I bind a keypress event so that it only fires when the tab containing the frame generating the event is active (i.e., for a button hotkey, how do I only capture the event while the button is on the active tab)?
Detail
I am writing a Tkinter application (my first), which uses a ttk.Notebook
object to manage multiple portions of the interface. I have multiple tabs, some of which have the "same" button on them, but which have different actions, depending on which tab is active (i.e., a "Save" button on one tab saves the items from that tab only, not from all tabs).
The intuitive way to do this is to bind the event to the frame, then the frame containing the "active" objects would catch the event, but this doesn't appear to work. However, if I bind the event to the root window, the same handler is called, regardless of the tab context.
I would think that this would be a common requirement, however I am unable to find information regarding how to do this.
I am using Python 3.4.3.
MCVE
Here is a minimum example, which demonstrates the behavior I have observed. It generates a main window with five tabs, each with an event binding for Alt-t, which should fire the event handler for the frame in that tab.
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()