classification
Title: Better repr for Tkinter event objects
Type: enhancement Stage: resolved
Components: Tkinter Versions: Python 3.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: python-dev, serhiy.storchaka, terry.reedy
Priority: normal Keywords: patch

Created on 2016-06-11 12:35 by serhiy.storchaka, last changed 2016-07-20 20:57 by terry.reedy. This issue is now closed.

Files
File name Uploaded Description Edit
tkinter_event_repr.patch serhiy.storchaka, 2016-06-11 17:02 review
tkinter_event_repr_key_state.patch serhiy.storchaka, 2016-06-11 22:53 review
tk-win-key-events.txt terry.reedy, 2016-06-12 00:18
tkinter_event_repr_key_state2.patch serhiy.storchaka, 2016-06-13 07:52 review
tk-win-key-events2.txt terry.reedy, 2016-06-13 19:20
Messages (18)
msg268209 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-11 12:35
Proposed patch adds better repr for tkinter.Event objects. Currently default repr shows only class name (always the same) and object address (not interesting, since event objects are short-living). The patch makes repr showing most event attributes in human-readable form.

For testing run following script. Press any keys (with modifiers), move and click mouse, select text, move and resize the window, switch to other windows.

import tkinter
t = tkinter.Text()
t.pack()
t.bind("<<Selection>>", print)
t.bind("<<debug>>", print)
for k in tkinter.EventType:
    try:
        t.event_add("<<debug>>", '<%s>' % k)
    except tkinter.TclError:
        pass

tkinter.mainloop()
msg268228 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-11 16:34
+1! This would be helpful for exploration and quite possibly for tests.  Earlier this year, I bound <Button-1> to a custom function(event) printing event.x, event.y so I could discover how the line thickness of Canvas rectangles was distributed inside and outside the nominal dimensions. (Using a magnifier to click on exact pixels, I discovered the rule.) Being able to bind to print instead have been nice. 

There is no patch uploaded.  In the absence of seeing what you did... Event.type should be decoded.  The hex address should be replaced by at least the widget class, if not its path name (which would make readable names imperative!) The Event representation should be customized to the event type.

For me, there is no tkinter.EventType. The <<Selection>> binding worked to prove the idea.
msg268231 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-11 16:50
Oops! Sorry, here is a patch.

Event.type is decoded. The address of the Event object is omitted as don't having much sense (this is short-living object). The name of widget is omitted since it is too long and usually know (in any case you can easy print both widget and event). Only non-default set attributes are output (thus the output depends on the type of the event).
msg268232 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-11 17:02
Sorry yet once. Uploaded patch contained experimental implementation. Here is cleaned patch.
msg268235 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-11 17:33
Is this something that you might push before a2 tomorrow?  (If I review now?) Or still in development?
msg268236 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-11 17:48
If you have no something to add, I'll push the patch.
msg268258 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-11 19:31
Testing now.
msg268264 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-11 20:16
Summary: Though I would like to see some refinements, this looks really useful as is and I would like it applied soon even if refinements have to wait for a second patch.

Moving the window did not generate a printed event.

I like the compact way of handling customization.  Two more possible exclusions: 1. The key state seems like it should only be interesting for key events.  2. The 4 mouse positions are pretty noisy and seem not relevant to key events, and to many other non-mouse events.

I wish "VirtualEvent event"s had the triggering sequence available, but you cannot change that.
.
msg268267 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-11 20:32
The key state can be interesting for mouse events too. Ctrl-Click, Shift-Move. Maybe it is worth to omit the output of state=0.

Agreed, the 4 mouse positions are pretty noisy. Maybe omit root_x and root_y? But mouse position can be relevant for such key events as pressing Ctrl. For example if the mouse pointer points on module name in import statement, pressing Ctrl can convert the name into a hyperling to a file of the module.
msg268272 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-11 21:00
Right.  This is why I suggested leaving anything we are not sure of to a later patch, after gaining more experience (and thought).

However, 'state' behaved strangely in my experiments.  In a sequence of about 900 events, it started as 8 (Left Alt according to Shipman, but I never touched the key) and changed to 0 here

<Leave event state=8 focus=False x=120 y=-19 x_root=966 y_root=321>
<Enter event state=8 focus=False x=797 y=482 x_root=1861 y_root=940>
<ButtonPress event state=8 num=1 x=797 y=482 x_root=1861 y_root=940>
<Motion event state=264 x=797 y=483 x_root=1861 y_root=941>
<VirtualEvent event state=0 x=0 y=0 x_root=0 y_root=0>

back to 8 here

<VirtualEvent event state=0 x=0 y=0 x_root=0 y_root=0>
<ButtonRelease event state=264 num=1 x=800 y=489 x_root=1864 y_root=947>
<Leave event state=8 focus=False x=800 y=489 x_root=1864 y_root=947>

and briefly back to 0 here

<ButtonPress event state=8 num=1 x=178 y=134 x_root=1293 y_root=631>
<VirtualEvent event state=0 x=0 y=0 x_root=0 y_root=0>
<ButtonRelease event state=264 num=1 x=178 y=134 x_root=1293 y_root=631>
<Motion event state=8 x=179 y=134 x_root=1294 y_root=631>
msg268275 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-06-11 21:20
New changeset 61a92a102b2d by Serhiy Storchaka in branch 'default':
Issue #27294: Improved repr for Tkinter event objects.
https://hg.python.org/cpython/rev/61a92a102b2d
msg268291 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-11 22:53
Next patch decodes the state attribute. Modifier names can be platform depended, please test on Windows. What modifiers correspond Shift, Ctrl, Alt, Win, CapsLock, etc?
msg268300 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-12 00:18
If you want more, say so, and I will do them after resting.
msg268429 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-13 07:52
Thank you Terry, this information is helpful. Mod1 is Alt on X11, but not on Windows.

It looks to me that on Windows Mod1 is NumLock, Mod3 is ScrollLock, 0x20000 is Alt, 0x40000 is pad keyboard. It is not clear about Win. What events are emitted if your press say Win-X?

On Linux (X11) Mod1 is Alt, Mod2 is NumLock, Mod4 is Win, 0x2000, 0x4000 and 0x6000 are alternative keyboard layouts. But many of this I presume is configurable.

Mac OS can have its own peculiarities.

I think on this stage it is better to left standard X11 modifiers (Shift, Lock, Control, Mod1-Mod5, Button1-Button5) and output the rest modifiers in hexadecimal. End user should interpret these names and numerics in platform depending way.
msg268793 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-18 10:38
According to Tk sources on Mac OSX: Mod1 is Command (=Meta), Mod2 is Option (=Alt), Mod3 is NumLock, Mod4 is Fn.
msg268823 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-06-18 18:55
New changeset e0ec4abe659f by Serhiy Storchaka in branch 'default':
Issue #27294: Numerical state in the repr for Tkinter event objects is now
https://hg.python.org/cpython/rev/e0ec4abe659f
msg268832 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-18 20:09
That's with this issue. I think we will return to Event repr after implementing named flags and providing standard mechanism for parsing and creating keystrokes (there are elements of this in IDLE).
msg270892 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-07-20 20:57
Addendum: I verified flag 8 is Mod1 is Numlock on Windows.  http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/event-handlers.html has table that claims that 8 is Left Alt and that 16 is NumLock. From what you say above, true on non-mac *nix, and only there.

Flag 32 is Mod3 = Scrolllock on Windows.

Question: autocomplete.py refers to event.mc_state in

    if hasattr(event, "mc_state") and event.mc_state:
        # A modifier was pressed along with the tab, continue as usual.
        return

It is not mentioned as an event field in either the NMT ref or http://www.tcl.tk/man/tcl8.6/TkCmd/event.htm#M29.  However, it seems to be the state minus any 'lock' flags, Nun/Caps/Scrolllock on Windows.  It must use a system-specific mask.  The only Google hit for "tk event mc_state" is my recent commit of test_autocomplete.py.  Is this a normal tk event attribute or a local addition?

There is also mc_type, which is 0 for a tab combinations.
History
Date User Action Args
2016-07-20 20:57:29terry.reedysetmessages: + msg270892
2016-07-20 20:19:29terry.reedysetmessages: - msg268826
2016-07-20 20:19:06terry.reedysetmessages: - msg268824
2016-06-18 20:09:22serhiy.storchakasetstatus: open -> closed
resolution: fixed
messages: + msg268832

stage: commit review -> resolved
2016-06-18 19:16:26serhiy.storchakasetmessages: + msg268826
2016-06-18 19:10:02python-devsetmessages: + msg268824
2016-06-18 18:55:46python-devsetmessages: + msg268823
2016-06-18 10:38:07serhiy.storchakasetmessages: + msg268793
2016-06-13 19:20:02terry.reedysetfiles: + tk-win-key-events2.txt
2016-06-13 07:52:23serhiy.storchakasetfiles: + tkinter_event_repr_key_state2.patch

messages: + msg268429
2016-06-12 00:18:04terry.reedysetfiles: + tk-win-key-events.txt

messages: + msg268300
2016-06-11 22:53:51serhiy.storchakasetfiles: + tkinter_event_repr_key_state.patch

messages: + msg268291
2016-06-11 21:20:33python-devsetnosy: + python-dev
messages: + msg268275
2016-06-11 21:00:51terry.reedysetmessages: + msg268272
2016-06-11 20:32:51serhiy.storchakasetmessages: + msg268267
2016-06-11 20:16:48terry.reedysetmessages: + msg268264
stage: patch review -> commit review
2016-06-11 19:31:41terry.reedysetmessages: + msg268258
2016-06-11 17:48:10serhiy.storchakasetmessages: + msg268236
2016-06-11 17:33:47terry.reedysetmessages: + msg268235
2016-06-11 17:02:33serhiy.storchakasetfiles: + tkinter_event_repr.patch

messages: + msg268232
2016-06-11 17:01:01serhiy.storchakasetfiles: - tkinter_event_repr.patch
2016-06-11 16:50:41serhiy.storchakasetfiles: + tkinter_event_repr.patch
keywords: + patch
messages: + msg268231
2016-06-11 16:34:40terry.reedysetmessages: + msg268228
2016-06-11 12:35:57serhiy.storchakacreate