Python Forum

Full Version: How to hardcode event.state? (tkinter)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have a small question.
if I print the key event while holding shift and control I see:
<KeyPress event state=Shift|Control|Mod2 keysym=Left keycode=113 x=-165 y=572>
But when I print event.state I see a number. That number is different on different systems. For example shift+left is event.state 1 on linux mint and event.state 16 on linux lite. How am I supposed to detect shift+other-key in a correct way?
This is the Python code that generates the state repl. Found in Python38/Lib/tkinter/__init__.py on my machine (Windows 10, Python 3.8).
    def __repr__(self):
        attrs = {k: v for k, v in self.__dict__.items() if v != '??'}
        if not self.char:
            del attrs['char']
        elif self.char != '??':
            attrs['char'] = repr(self.char)
        if not getattr(self, 'send_event', True):
            del attrs['send_event']
        if self.state == 0:
            del attrs['state']
        elif isinstance(self.state, int):
            state = self.state
            mods = ('Shift', 'Lock', 'Control',
                    'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5',
                    'Button1', 'Button2', 'Button3', 'Button4', 'Button5')
            s = []
            for i, n in enumerate(mods):
                if state & (1 << i):
                    s.append(n)
            state = state & ~((1<< len(mods)) - 1)
            if state or not s:
                s.append(hex(state))
            attrs['state'] = '|'.join(s)
So for this machine shift=1, lock=2, control=4, mod1=8, etc I did not find where any of these are defined as constants or enumerations. My guess is they come directly from the C Tk library.

I think you are looking at the problem backward. You should not be binding a keypress event and then trying to figure out the key. The file mentioned above also contains this info:
Quote: def bind(self, sequence=None, func=None, add=None):
"""Bind to this widget at event SEQUENCE a call to function FUNC.

SEQUENCE is a string of concatenated event
patterns. An event pattern is of the form
<MODIFIER-MODIFIER-TYPE-DETAIL> where MODIFIER is one
of Control, Mod2, M2, Shift, Mod3, M3, Lock, Mod4, M4,
Button1, B1, Mod5, M5 Button2, B2, Meta, M, Button3,
B3, Alt, Button4, B4, Double, Button5, B5 Triple,
Mod1, M1. TYPE is one of Activate, Enter, Map,
ButtonPress, Button, Expose, Motion, ButtonRelease
FocusIn, MouseWheel, Circulate, FocusOut, Property,
Colormap, Gravity Reparent, Configure, KeyPress, Key,
Unmap, Deactivate, KeyRelease Visibility, Destroy,
Leave and DETAIL is the button number for ButtonPress,
ButtonRelease and DETAIL is the Keysym for KeyPress and
KeyRelease. Examples are
<Control-Button-1> for pressing Control and mouse button 1 or
<Alt-A> for pressing A and the Alt key (KeyPress can be omitted).
An event pattern can also be a virtual event of the form
<<AString>> where AString can be arbitrary. This
event can be generated by event_generate.
If events are concatenated they must appear shortly
after each other.
From that, I think you should bind events like window.bind("<Shift-KeyPress-Left>", left_keypress_func), performing a separate bind for each key.