From: Martin v. Loewis on
I'm running the script

ttk::notebook .nb
..nb add [label .nb.l1 -text hello] -text a
..nb add [label .nb.l2 -text world] -text b
pack .nb
focus .nb
puts [.nb select]
event generate .nb <Key-Right>
puts [.nb select]

and expect that the second output should display ".nb.l2", yet it shows
".nb.l1" still. I.e. the event generate has no effect.

The key is bound correctly, though: if I manually hit the right key, the
notebook properly cycles between tabs.

This is all with Tcl 8.5.8, on Debian AMD64.

What am I doing wrong?

TIA,
Martin
From: Joe English on
Martin v. Loewis wrote:
> I'm running the script
>
> ttk::notebook .nb
> .nb add [label .nb.l1 -text hello] -text a
> .nb add [label .nb.l2 -text world] -text b
> pack .nb
> focus .nb
> puts [.nb select]
> event generate .nb <Key-Right>
> puts [.nb select]
>
> and expect that the second output should display ".nb.l2", yet it shows
> ".nb.l1" still. I.e. the event generate has no effect.

Here's what's happening:

<KeyPress> and <KeyRelease> events are always sent
to the widget with focus, regardless of which window
was passed to [event generate] (*).

And even though you have said [focus .nb], the .nb widget
does not (yet) have focus. This could be because the window
has not yet been mapped, or because the window manager has not
given your application the focus, or for some other reason.

To fix: you could call [update] after managing all the windows
and before setting [focus]; this will not be reliable however
as the WM might still decline to give your application focus.

Or, better yet, if you just want a particular tab to be initially
selected, then just say so: [.nb select .nb.l2].

But basically, using [event generate] to send key events is
unreliable; avoid it if you can.


(*) I'm beginning to think this is the Wrong Thing;
we should seriously consider changing this behavior
in Tk 9 if that ever happens.



--Joe English