我尝试使用 wx.TextCtrl 捕获键入的按键事件,并将键入的按键直接转发到子进程的标准输入。请注意,出于我的特殊目的,我将
完全禁用 TextCtrl 的文本编辑功能。也就是说,当我输入一封信时,
信件不会出现在TextCtrl上,它会被直接转发。
这是一些代码来说明我想要的。
# inside the main frame
self.text = wx.TextCtrl(self.panel, wx.ID_ANY, style=wx.TE_MULTILINE)
self.text.Bind(wx.EVT_KEY_DOWN, self.OnKey)
self.text.Bind(wx.EVT_CHAR, self.OnChar)
# ...
def OnKey(self, evt):
keycode = evt.GetKeyCode()
# ENTER
if keycode == 13:
self.subprocess.stdin.read("\n")
if keycode == 9:
self.subprocess.stdin.read("\t")
if keycode == 8:
self.subprocess.stdin.read("\b")
if keycode == 316:
pass # maybe some key will be ignored
else:
evt.skip()
def OnChar(self, evt):
key=chr(keycode)
self.subprocess.stdin.read(key)
我想将“ENTER”、“TAB”、“BACKSPACE”、字符、数字等所有按键输入事件转发到stdin,而不让TextCtrl干扰。有没有好的办法呢?或者我必须一一明确地匹配每个键?
感谢您的任何建议!
您可以执行以下操作将按键代码转换为字符:
chr(keycode)
但这并不能获得所有内容,例如输入和选项卡。您必须根据具体情况进行处理(就像您在示例中所做的那样)。否则,您需要创建一个按键代码到字符映射的字典:
codemap = {97:'a', 98:'b', 8:'\b'} # Fill this out
self.subprocess.stdin.read(codemap[keycode])
您可能还想使用 wx.TE_PROCESS_ENTER 和 wx.TE_PROCESS_TAB。它们启用/禁用将 Enter 和 Tab 键捕获为文本。
在这里您可以找到“key”python 模块上的一些修饰符和键状态:
https://pythonhosted.org/pyglet/programming_guide/keyboard_events.html
您只能使用 1 个活页夹,例如 @KEY_DOWN,而不能同时使用 @KEY_DOWN 和 EVT_CHAR
要操作字符,您需要检查值的范围,但可以使用上面网站上的信息,例如:
key.A
识别“a”。
否则,您可以通过关联的键码(unicode 或 ASCII)来识别“a”。
您需要从“evt”KeyEvent 获取:
evt.GetRawKeyCode()
要识别按 SHIFT 和 CTRL SX ecc 等修饰键:
evt.GetModifiers()
这里,作为“key”模块的使用示例,我制作了一个侦听器,使 TextCtrl 仅接受数字值输入。如果需要,您可以修改它。 对于字母,您需要检查以下来源的数值: 65 (A) 至 90 (Z) 以及 97 (a) 至 122 (z)。
from pyglet.window import key
FLOAT_POINT = "."
ENTRY_ID = "id"
ENTRY_KEY_EVENT = "keyEvent"
ENTRY_SELECTION_EVENT = "selectionEvent"
MASK_STARTED_RIGHT_SELECTION = 1
MASK_STARTED_LEFT_SELECTION = -1
class KeyboardEventUtils(object):
__mLastEvt = {}
def check_input_key_only_numeric_value(value, strng):
return value.isnumeric() or (value == FLOAT_POINT and not FLOAT_POINT in strng and len(strng) > 0)
def on_change_text_check_is_int_value(self, evt):
txt = evt.GetEventObject()
value = chr(evt.GetUnicodeKey())
if KeyboardEventUtils.__mLastEvt != None and len(KeyboardEventUtils.__mLastEvt) > 0 and KeyboardEventUtils.__mLastEvt[ENTRY_ID] != txt.GetId():
self._mLastEvt = {}
if check_input_key_only_numeric_value(value, txt.GetValue()):
pos = txt.GetInsertionPoint()
txt.SetValue(txt.GetValue()[:pos] + value + txt.GetValue()[pos:])
txt.SetInsertionPoint(pos + 1)
elif (evt.GetModifiers() == 4 or evt.GetModifiers() == key.MOD_SHIFT) and evt.GetRawKeyCode() == key.LEFT: # 4 (?) key.MOD_SHIFT (?) TO FIX
pos = txt.GetInsertionPoint()
rng = list(txt.GetSelection())
if rng[0] == rng[1] and ENTRY_SELECTION_EVENT in KeyboardEventUtils.__mLastEvt:
del KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT]
if ENTRY_SELECTION_EVENT in KeyboardEventUtils.__mLastEvt and KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT] == MASK_STARTED_RIGHT_SELECTION:
rng[1] = rng[1] - 1
else:
KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT] = MASK_STARTED_LEFT_SELECTION
rng[0] = rng[0] - 1
txt.SetSelection(rng[0], rng[1])
elif (evt.GetModifiers() == 4 or evt.GetModifiers() == key.MOD_SHIFT): # 4 (?) key.MOD_SHIFT (?) TO FIX
pos = txt.GetInsertionPoint()
rng = list(txt.GetSelection())
if rng[0] == rng[1] and ENTRY_SELECTION_EVENT in KeyboardEventUtils.__mLastEvt:
del KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT]
if ENTRY_SELECTION_EVENT in KeyboardEventUtils.__mLastEvt and KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT] == MASK_STARTED_LEFT_SELECTION:
rng[0] = rng[0] + 1
else:
KeyboardEventUtils.__mLastEvt[ENTRY_SELECTION_EVENT] = MASK_STARTED_RIGHT_SELECTION
rng[1] = rng[1] + 1
txt.SetSelection(rng[0], rng[1])
elif evt.GetRawKeyCode() == key.LEFT:
rng = list(txt.GetSelection())
if rng[0] != rng[1]:
txt.SetInsertionPoint(rng[0])
else:
txt.SetInsertionPoint(txt.GetInsertionPoint() - 1)
elif evt.GetRawKeyCode() == key.RIGHT:
rng = list(txt.GetSelection())
if rng[0] != rng[1]:
txt.SetInsertionPoint(rng[1])
else:
txt.SetInsertionPoint(txt.GetInsertionPoint() + 1)
elif evt.GetRawKeyCode() == key.UP or evt.GetRawKeyCode() == key.DOWN:
pass
elif evt.GetRawKeyCode() == key.BACKSPACE:
pos = txt.GetInsertionPoint()
if txt.GetStringSelection() == "":
txt.SetValue(txt.GetValue()[:pos-1] + txt.GetValue()[pos:])
txt.SetInsertionPoint(pos - 0x1)
else:
r = txt.GetSelection()
txt.SetValue(txt.GetValue()[:r[0]] + txt.GetValue()[r[1]:])
txt.SetInsertionPoint(pos)
elif evt.GetRawKeyCode() == key.DELETE:
pos = txt.GetInsertionPoint()
if txt.GetStringSelection() == "":
txt.SetValue(txt.GetValue()[:pos] + txt.GetValue()[pos+1:])
else:
r = txt.GetSelection()
txt.SetValue(txt.GetValue()[:r[0]] + txt.GetValue()[r[1]:])
txt.SetInsertionPoint(pos)
elif evt.GetModifiers() == key.MOD_CTRL and evt.GetRawKeyCode() == key.A:
txt.SelectAll()
else:
KeyboardEventUtils.__mLastEvt[ENTRY_ID] = txt.GetId()
KeyboardEventUtils.__mLastEvt[ENTRY_KEY_EVENT] = evt
return False
KeyboardEventUtils.__mLastEvt[ENTRY_ID] = txt.GetId()
KeyboardEventUtils.__mLastEvt[ENTRY_KEY_EVENT] = evt
return True