简体   繁体   中英

Python tkinter bindtag Event handling - how to update which tab is currently selected

I am new to Python and is about to build a GUI using tkinter. The GUI consists of a Notebook and I am trying to create a event handler for when the user click with the mouse on the different tabs. However when I click on a tab, the handlerfunction 'works' but it seems the selected tab is not 'updated' before the function is called.

As a sidenote: So far I have mainly used 'Tkinter 8.5 reference: a GUI for Python (Shipman)'. Please see code below. Grateful for any suggestions!

from tkinter import *
import tkinter.ttk as ttk

root = Tk()
note = ttk.Notebook(root)

tab1 = Frame(note,width = 10)
tab2 = Frame(note,width = 10)
tab3 = Frame(note,width = 10)

note.add(tab1, text = "Tab One")
note.add(tab2, text = "Tab Two")
note.add(tab3, text = "Tab Three")
note.grid()

def personalData(event):
    if event.widget.index("current") == 0:    
       print("One!") 
    else:
       print("Not One!") 

note.bind('<1>',personalData)
root.mainloop()

The reason this is happening is due to the order that events are processed. Custom bindings on widgets are processed before the built-in bindings, meaning that your binding on <1> will fire before the tab actually changes. For more information, research "binding tags" (or sometimes called "bind tags" or "bindtags").

A better solution is to bind on the virtual event <<NotebookTabChanged>> , which the notebook will generate after the tab has changed.

Example:

note.bind("<<NotebookTabChanged>>", personalData)

An additional benefit to binding to the virtual event rather than a mouse click is that the event will fire even if the tab is changed via some other mechanism besides a mouse click. For example, if a tab has the keyboard focus, you can select the next or previous tab using the arrow keys on your keyboard.

You're experiencing this because events of bind are handled before events of bindtags , in other words, you're actually not changing the tab before the callback function to "<1>" event, personalData is handled.


One workaround would be to rotate the order of the sequence which the events are being handled with. Add after note.bind(...) :

note.bindtags((note.bindtags()[1:] + note.bindtags()[:1]))

this will put the bind's callback as the last in the sequence and shift the rest to up in the queue.


Another way would be to replace the actual event( "<1>" ) to a more appropriate one like in Novel's suggestion .

Note that when you click another tab, the current tab is still the previous tab; if you change your binding to

note.bind('<ButtonRelease-1>',personalData)

it will work right, as now, when the mouse button is released, the current tab is the tab already selected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM