捕获 TextCtrl 的键/字符事件并将键入的键转发到子进程的标准输入

问题描述 投票:0回答:2

我尝试使用 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干扰。有没有好的办法呢?或者我必须一一明确地匹配每个键?

感谢您的任何建议!

python user-interface wxpython wxwidgets keyboard-events
2个回答
0
投票

您可以执行以下操作将按键代码转换为字符:

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 键捕获为文本。


0
投票

在这里您可以找到“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
© www.soinside.com 2019 - 2024. All rights reserved.