Mac OS X 10.6.6 - Tkinter
I want to bind multiple-key events, and while I have found an effbot article and the Tk man pages, I\'ve been unable to make this work corr
Option 1
Something like this:
# Status of control, shift and control+shift keys in Python
import tkinter as tk
ctrl = False
shift = False
ctrl_shift = False
def key(event):
global ctrl, shift, ctrl_shift
#print(event.keycode, event.keysym, event.state)
if ctrl_shift:
print('++{}'.format(event.keysym))
elif ctrl:
print('+{}'.format(event.keysym))
elif shift:
print('+{}'.format(event.keysym))
ctrl = False
shift = False
ctrl_shift = False
def control_key(state, event=None):
''' Controll button is pressed or released '''
global ctrl
ctrl = state
def shift_key(state, event=None):
''' Controll button is pressed or released '''
global shift
shift = state
control_shift(state)
def control_shift(state):
''' + buttons are pressed or released '''
global ctrl, ctrl_shift
if ctrl == True and state == True:
ctrl_shift = True
else:
ctrl_shift = False
root = tk.Tk()
root.geometry('256x256+0+0')
root.event_add('<>', '', '')
root.event_add('<>', '', '')
root.event_add('<>', '', '')
root.event_add('<>', '', '')
root.bind('<>', lambda e: control_key(True))
root.bind('<>', lambda e: control_key(False))
root.bind('<>', lambda e: shift_key(True))
root.bind('<>', lambda e: shift_key(False))
root.bind('', key)
root.mainloop()
Option 2
However, in the end, I decided to process keystrokes manually. You can se the example in this file. First, I set keycodes and shortcuts in two dictionaries self.keycode and self.__shortcuts:
# List of shortcuts in the following format: [name, keycode, function]
self.keycode = {} # init key codes
if os.name == 'nt': # Windows OS
self.keycode = {
'o': 79,
'w': 87,
'r': 82,
'q': 81,
'h': 72,
's': 83,
'a': 65,
}
else: # Linux OS
self.keycode = {
'o': 32,
'w': 25,
'r': 27,
'q': 24,
'h': 43,
's': 39,
'a': 38,
}
self.__shortcuts = [['Ctrl+O', self.keycode['o'], self.__open_image], # 0 open image
['Ctrl+W', self.keycode['w'], self.__close_image], # 1 close image
['Ctrl+R', self.keycode['r'], self.__roll], # 2 rolling window
['Ctrl+Q', self.keycode['q'], self.__toggle_poly], # 3 toggle between roi/hole drawing
['Ctrl+H', self.keycode['h'], self.__open_poly], # 4 open polygons for the image
['Ctrl+S', self.keycode['s'], self.__save_poly], # 5 save polygons of the image
['Ctrl+A', self.keycode['a'], self.__show_rect]] # 6 show rolling window rectangle
Then added self.__keystroke function to monitor keystroke events. This function checks if key is pressed or not:
def __keystroke(self, event):
""" Language independent handle events from the keyboard """
#print(event.keycode, event.keysym, event.state) # uncomment it for debug purposes
if event.state - self.__previous_state == 4: # check if key is pressed
for shortcut in self.__shortcuts:
if event.keycode == shortcut[1]:
shortcut[2]()
else: # remember previous state of the event
self.__previous_state = event.state
Finally, bind the self.__keystroke function to the master GUI window. Note that this function is bonded in the idle mode, because multiple keystrokes slow down the program on weak computers:
# Handle keystrokes in the idle mode, because program slows down on a weak computers,
# when too many key stroke events in the same time.
self.master.bind('', lambda event: self.master.after_idle(self.__keystroke, event))