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
Command 'X86_64-Linux-Gnu-Gcc' Failed with Exit Status 1
Why Xgrabkey Generates Extra Focus-Out and Focus-In Events
/Usr/Bin/Env: Python2: No Such File or Directory
Trying to Import Pypyodbc Module Gives Error 'Odbc Library Is Not Found. Is Ld_Library_Path Set'
Cat, Grep and Cut - Translated to Python
Unit Testing File Modifications
How to Solve Unicodedecodeerror in Python 3.6
Loading a Config File from Operation System Independent Place in Python
Why Can't My Post-Receive Hook Run a Virtualenv Source Command
Virtualenv Uses Wrong Python, Even Though It Is First in $Path
How to Declare Custom Exceptions in Modern Python
Convert Utc Datetime String to Local Datetime
Difference Between Venv, Pyvenv, Pyenv, Virtualenv, Virtualenvwrapper, Pipenv, etc
How to Get Hard Disk Serial Number Using Python
Behaviour of Increment and Decrement Operators in Python
What Is the Naming Convention in Python For Variable and Function