1

I encountered an issue regarding KeyPress binds in tkinter when switching between Windows and Linux while using a NumPad. Using self.bind("-", function) works on Windows, however is not triggered on Linux.

With the following code snippet I found out that the events of a keyboard-minus differs from a numpad-minus.

Code:

import tkinter as tk


class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.bind("<Key>", self.action)
        self.count = 0

    def action(self, e):
        print(e)
        self.count += 1


app = App()
app.mainloop() 

Output:

NumPad:
<KeyPress event state=Mod2 keysym=KP_Subtract keycode=82 char=‘-‘ x=323 y=-184

KeyBoard:
<KeyPress event state=Mod2 Keysym=minus keycode=61 char=’-‘ x=376 y=-27 

Is there a way to make Linux recognize the "-" char in a tkinter bind whether it is from keyboard or NumPad?

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
Valac
  • 29
  • 10
  • You could always bind both keysyms, to the same function. – jasonharper Aug 19 '20 at 13:18
  • Another thing you could do is keep binding to any key, as in your code in this question, and dispatch based on the `char` attribute of the event, since it's the same for both keys. – Sven Marnach Aug 19 '20 at 19:31

1 Answers1

1

Is there a way to make Linux recognize the "-" char from both the keyboard and the NumPad in a tkinter bind?

I have wrote code where you can choose from the OptionMenu from the options you have:

You could bind both keysyms to the same function. – jasonharper

keep binding to any key and dispatch based on the char attribute of the event. – Sven Marnach

use both the upper methods.

Running the provided code you can see that binding to both, 'any key' and the 'minus' key suppresses the key event for pressing 'any key' to be triggered in case the 'minus' key is pressed:

# https://stackoverflow.com/questions/63464407/cannot-bind-numpad-minus-key-on-linux-with-tkinter
import tkinter as tk

enable = None
# enable = 'binding and action'
# enable = 'binding only'
# enable = 'only action'

class App(tk.Tk):
    def __init__(self):
        global enable
        from tkinter import StringVar, OptionMenu
        tk.Tk.__init__(self)
        choices = ['binding and action', 'binding only', 'only action']
        self.sv = StringVar()
        
        if enable == None:
            print("DEFAULT CHOICE: enable == 'binding and action'")
            enable = 'binding and action'

        if enable == 'binding and action': 
            self.bind("<KP_Subtract>", self.on_minus_bind)
            self.bind("<minus>"      , self.on_minus_bind)
            self.bind("<Key>",         self.action)
            self.sv.set('binding and action')

        if enable == 'binding only': 
            self.bind("<KP_Subtract>", self.on_minus_bind)
            self.bind("<minus>"      , self.on_minus_bind)
            self.sv.set('binding only')

        if enable == 'only action': 
            self.bind("<Key>",         self.action)
            self.sv.set('only action')
            
        self.om = OptionMenu(None, self.sv, *choices, command=self.on_option_change)
        self.om.pack()
        
        self.count = 0

    def on_option_change(self, e):
        enable = self.sv.get()
            
        if enable == 'binding and action': 
            self.bind("<KP_Subtract>", self.on_minus_bind)
            self.bind("<minus>"      , self.on_minus_bind)
            self.bind("<Key>",         self.action)

        if enable == 'binding only': 
            self.unbind("<Key>")
            self.bind("<KP_Subtract>", self.on_minus_bind)
            self.bind("<minus>"      , self.on_minus_bind)

        if enable == 'only action': 
            self.unbind("<KP_Subtract>")
            self.unbind("<minus>")
            self.bind("<Key>",         self.action)

    def action(self, e):
        if e.char == '-':
            self.on_minus_action(e)
        else: 
            print('action call: ', e, type(e))
        self.count += 1
    
    def on_minus_bind(self, e):
        print('bind-event :  "minus" pressed', e, type(e))

    def on_minus_action(self, e): 
        print('action-call:  "minus" pressed', e, type(e) )

app = App()
app.mainloop() 
Claudio
  • 7,474
  • 3
  • 18
  • 48