我知道并使用很多绑定语法, 但是我怎样才能直接检查事件对象并提取所按下的字母,例如'c'和修饰符e,g,'Control'和'Alt'?
我试过这个
def reportEvent(event):
eventDict = {
'2': 'KeyPress', '3': 'KeyRelease', '4': 'ButtonPress', '5': 'ButtonRelease', '6': 'Motion', '7': 'Enter',
'8': 'Leave', '9': 'FocusIn', '10': 'FocusOut', '12': 'Expose', '15': 'Visibility', '17': 'Destroy',
'18': 'Unmap', '19': 'Map', '21': 'Reparent', '22': 'Configure', '24': 'Gravity', '26': 'Circulate',
'28': 'Property', '32': 'Colormap','36': 'Activate', '37': 'Deactivate'}
rpt = '\n\n%s' % (80*'=')
rpt = '%s\nEvent: type=%s (%s)' % (rpt, event.type,eventDict.get(event.type, 'Unknown'))
rpt = '%s\ntime=%s' % (rpt, event.time)
rpt = '%s widget=%s' % (rpt, event.widget)
rpt = '%s x=%d, y=%d'% (rpt, event.x, event.y)
rpt = '%s x_root=%d, y_root=%d' % (rpt, event.x_root, event.y_root)
rpt = '%s y_root=%d' % (rpt, event.y_root)
rpt = '%s\nserial=%s' % (rpt, event.serial)
rpt = '%s num=%s' % (rpt, event.num)
rpt = '%s height=%s' % (rpt, event.height)
rpt = '%s width=%s' % (rpt, event.width)
rpt = '%s keysym=%s' % (rpt, event.keysym)
rpt = '%s ksNum=%s' % (rpt, event.keysym_num)
#### Some event types don't have these attributes
try:
rpt = '%s focus=%s' % (rpt, event.focus)
except:
try:
rpt = '%s send=%s' % (rpt, event.send_event)
except:
pass
print rpt
被盗到 Python和Tkinter编程,但它没有显示我正在按的最终修饰符
答案 0 :(得分:5)
从理论上讲,这可以解决您的问题:
from tkinter import *
root = Tk()
mods = {
0x0001: 'Shift',
0x0002: 'Caps Lock',
0x0004: 'Control',
0x0008: 'Left-hand Alt',
0x0010: 'Num Lock',
0x0080: 'Right-hand Alt',
0x0100: 'Mouse button 1',
0x0200: 'Mouse button 2',
0x0400: 'Mouse button 3'
}
root.bind( '<Key>', lambda e: print( 'Key:', e.char,
'Mods:', mods.get( e.state, None )))
root.mainloop()
然而,它不应该工作 - 或者至少它不是我的匈牙利苹果键盘,这是一个110键布局..
无论如何,这里是事件对象的所有属性:http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/event-handlers.html
答案 1 :(得分:2)
在Peter Varo's idea的帮助下,我有点为我工作(运行Windows 10和python 3.4)。
from tkinter import *
def onKeyDown(e):
# The obvious information
c = e.keysym
s = e.state
# Manual way to get the modifiers
ctrl = (s & 0x4) != 0
alt = (s & 0x8) != 0 or (s & 0x80) != 0
shift = (s & 0x1) != 0
# Merge it into an output
# if alt:
# c = 'alt+' + c
if shift:
c = 'shift+' + c
if ctrl:
c = 'ctrl+' + c
print(c)
# Run the tk window
root = Tk()
root.bind('<Key>', onKeyDown)
root.mainloop()
alt
键在我的情况下是错误的(它始终被按下),但ctrl
和shift
正常工作。
请注意,第一次按下ctrl
或shift
键时,它会将其注册为主键,而不是修改器。如果你稍后再拿它,它只会是一个修饰符。
因此您需要将其按键组合(例如Ctrl+a
)。因此,按a
然后按ctrl
会产生一个有点奇怪的结果(它会忽略a并将ctrl标记为主键,但不能作为修饰符)。
答案 2 :(得分:1)
以下脚本纠正了先前答案中使用的不合适的位标志,并考虑了ex:state = Shift | Alt | Control将不与Modifier字典中的任何内容匹配。需要将其作为位标志进行处理,并逐位匹配。
对此,任何用户都需要考虑的是,所有的Lock键(如果已打开)都将在event.state中报告,说明您是否要求。例如:打开CapsLock和NumLock并尝试捕获Alt + Control〜您实际上将获得“ CapsLock + NumLock + Control + Alt”。解决该问题的最简单方法是,只需从Modifier字典中删除所有ModN键。
据我所知,只能通过keysym属性捕获特定的_L和_R键。 state属性将始终包含该键的通用修饰符位标志。
#python 3.8
from tkinter import *
root = Tk()
Modifier = {
0x1 : 'Shift' ,
0x2 : 'CapsLock' ,
0x4 : 'Control' ,
0x8 : 'NumLock' , #Mod1
0x10 : 'Mod2' , #?
0x20 : 'ScrollLock' , #Mod3
0x40 : 'Mod4' , #?
0x80 : 'Mod5' , #?
0x100 : 'Button1' ,
0x200 : 'Button2' ,
0x400 : 'Button3' ,
0x800 : 'Button4' ,
0x1000 : 'Button5' ,
0x20000: 'Alt' , #not a typo
}
root.bind( '<Key>', lambda e: print(' + '.join([v for k, v in Modifier.items() if k & e.state])))
root.mainloop()
EventType是一个枚举。无需创建重复此枚举的整个字典。您可以使用event.type.name获取EventType的名称,并使用event.type.value访问该值。如果您绝对必须克隆Enum作为dict,则可以使用以下方法更彻底(更轻松)地完成此操作:
#python 3.8
# EventType Lookup
BindMap = {i.name:i.value for i in EventType}
# A few aliases that wont be returned from the generator
BindMap['Key'] = '2'
BindMap['Button'] = '4'
BindMap['Double'] = '4'
BindMap['Triple'] = '4'