Jimmy
Jimmy

Reputation: 145

How to bind the <Button-1> to the notebook tab?

There are some tabs, I want to do something if choose one of them. Please consider below code sample:

ttk::notebook .n
pack .n
frame .n.a
frame .n.b
pack .n.a -side left
pack .n.b -side left
.n add .n.a -text A
.n add .n.b -text B
bind .n <Button-1> {on_click}

proc on_click {} {
    set a [.n select]
    puts $a
    if {$a eq ".n.b"} {
        ....
    }
}

But when I click the tab B first time, I still get the output ".n.a". Or if I change to click another tab, the output is still previous tab. Seems "[.n select]" delay? How can I get the real current selected tab, after I click the tab?

Upvotes: 0

Views: 507

Answers (2)

Schelte Bron
Schelte Bron

Reputation: 4813

The order in which bindings are processed is determined by the bindtags of a widgets. If you check the bindtags for your notebook, you will see the following:

% bindtags .n
.n TNotebook . all

The notebook class bindings (TNotebook) take care of switching tabs when you click on them. Due to the order of the bindtags, your binding on the widget itself runs before the class bindings. That's why you still get the old tab.

One way to solve this is by adding another bindtag after the class binding and binding the event on that.

% bindtags .n {.n TNotebook NBTab . all}
% bind NBTab <Button-1> {on_click}

However, there's an easier way. The ttk::notebook widget provides a virtual event <<NotebookTabChanged>>, which fires after a new tab is selected. Binding your on_click proc to that event has a few advantages: The proc will also be called when the tab is changed using the keyboard and it does not run if the user clicks on an already selected tab.

Note: There is no need to pack frames if immediately after you add them to the notebook. Widgets can only be managed by one geometry manager. So adding them to the notebook will undo the pack commands.

Upvotes: 0

Jerry
Jerry

Reputation: 71558

There is indeed a 'delay', because of the bind you are using. There are 2 (at least, to my knowledge) events happening when you issue a mouse click:

  1. Button Press
  2. Button Release

While using 'Button' tells the interpreter to bind to the button press event, most applications actually do something on button release (e.g. if you press an 'OK' button and hold the click down, usually nothing will happen, and something will happen only after releasing the click).

With that in mind, if you change your bind to bind .n <ButtonRelease-1> {on_click}, then you get the outcome you are looking for.

For reference, please see the manual on bind.

Upvotes: 1

Related Questions