Cannot Bind Numpad Minus Key on Linux with Tkinter

Cannot bind NumPad minus key on Linux with Tkinter

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()

Numpad not working in pygame

The Pygame KEYDOWN event stores the alphanumeric zone numbers in the range 48 - 57 (0x30 - 0x39), as it should. However, numpad presses are reported in the range 256 - 265 (0x100 - 0x109), regardless of whether numlock is toggled.

The reason the printout of the value of Numpad 1 is displayed as "à" is because the key value for Numpad 1 is 257, which in Unicode is à (U+0101).

Here is a quick snippet that should convert numpad presses to their ASCII key value equivalent (does not convert other numpad keys, like Enter, +, or Delete, which also have different values than their equivalents elsewhere on the keyboard):

if (event.key >= 0x100 and event.key <= 0x109):
return event.key - 0xD0
else:
return event.key

How to obtain the keycodes in Python

See tty standard module. It allows switching from default line-oriented (cooked) mode into char-oriented (cbreak) mode with tty.setcbreak(sys.stdin). Reading single char from sys.stdin will result into next pressed keyboard key (if it generates code):

import sys
import tty
tty.setcbreak(sys.stdin)
while True:
print ord(sys.stdin.read(1))

Note: solution is Unix (including Linux) only.

Edit: On Windows try msvcrt.getche()/getwche(). /me has nowhere to try...


Edit 2: Utilize win32 low-level console API via ctypes.windll (see example at SO) with ReadConsoleInput function. You should filter out keypresses - e.EventType==KEY_EVENT and look for e.Event.KeyEvent.wVirtualKeyCode value. Example of application (not in Python, just to get an idea) can be found at http://www.benryves.com/tutorials/?t=winconsole&c=4.

How to bind Ctrl+/ in python tkinter?

Use <Control-slash>:

def quit(event):
print "you pressed control-forwardslash"
root.quit()

root = tk.Tk()
root.bind('<Control-slash>', quit) # forward-slash
# root.bind('<Control-backslash>', quit) # backslash
root.mainloop()

I don't have a link to a complete list of these event names. Here is a partial list I've collected:

| event                 | name                  |
| Ctrl-c | Control-c |
| Ctrl-/ | Control-slash |
| Ctrl-\ | Control-backslash |
| Ctrl+(Mouse Button-1) | Control-1 |
| Ctrl-1 | Control-Key-1 |
| Enter key | Return |
| | Button-1 |
| | ButtonRelease-1 |
| | Home |
| | Up, Down, Left, Right |
| | Configure |
| window exposed | Expose |
| mouse enters widget | Enter |
| mouse leaves widget | Leave |
| | Key |
| | Tab |
| | space |
| | BackSpace |
| | KeyRelease-BackSpace |
| any key release | KeyRelease |
| escape | Escape |
| | F1 |
| | Alt-h |


Related Topics



Leave a reply



Submit