wxPython中的组事件

wxPython中的组事件,python,wxpython,Python,Wxpython,我想在wxPython中处理两个事件。具体地说,我想将ON_KEY\u DOWN和CHAR事件分组,以调用一个方法,其中包含关于按下哪个键以及这个字符将产生什么(如果有的话)的信息 引用文件: 虽然这两个函数都可以用于wxEVT_KEY_DOWN、wxEVT_KEY_UP和wxEVT_CHAR类型的事件,但它们返回的值对于前两个事件和最后一个事件是不同的。对于后者,返回的键对应于用户按下键时将出现在文本区域中的字符。因此,其值取决于Shift键的当前状态,对于字母,取决于Caps Lock修改器

我想在wxPython中处理两个事件。具体地说,我想将
ON_KEY\u DOWN
CHAR
事件分组,以调用一个方法,其中包含关于按下哪个键以及这个字符将产生什么(如果有的话)的信息

引用文件:

虽然这两个函数都可以用于wxEVT_KEY_DOWN、wxEVT_KEY_UP和wxEVT_CHAR类型的事件,但它们返回的值对于前两个事件和最后一个事件是不同的。对于后者,返回的键对应于用户按下键时将出现在文本区域中的字符。因此,其值取决于Shift键的当前状态,对于字母,取决于Caps Lock修改器的状态。例如,如果在不按住Shift键的情况下按下某个键,则为该按键生成的wxEVT_CHAR类型的wx.KeyEvent将返回(从GetKeyCode或GetUnicode返回,因为它们对于ASCII字符的含义一致)97的键代码,对应于。如果按下同一个键,但按住Shift键(或Caps Lock处于活动状态),则该键可能为65,即大写字母A的ASCII值。但是,对于向下键和向上键事件,返回的键代码将与修改键的状态无关,即,它仅取决于按下的物理键,不会使用当前键盘状态转换为其逻辑表示形式

问题是我想要两个信息。如果按下一个键,我希望有“原始键代码”,如向上键或向下键,以及相应的键入字符(如果有)。我试图想出一个解决办法。但是
CHAR
并不是一直被提升的(有些按键不会产生任何字符)

文档给出了shift和CapLock示例,这有点奇怪。但是,并不是所有的用户都有QWERTY键盘。这就更有意义了:如果用户用AZERTY键盘按下QWERTY中1位数字对应的字母,那么a将被写入(按键向下。按键代码将产生
'1'
,而
CHAR.KeyCode
将产生
&
。这更有意义吗

那么,如何截获这两个事件,并使用这两种信息调用一个和一个方法(要知道,
CHAR
不会总是被引发)

我想我已经找到了一个解决方案:如果我可以访问事件循环或事件处理程序的事件队列,也许我可以检查:如果引发了
KEY\u DOWN
事件,那么我检查下一个事件是否是
CHAR
,如果是,从
CHAR
中检索所需的信息并调用单个方法。但我不知道怎么做而且文档没有(据我所知)准确描述何时引发
CHAR
事件(它可能不完全在
KEY\u DOWN
之后,它可能就在
KEU UP
之前,或者在这行的某个地方)

另一种可能是“强制”wx将
KEY\u DOWN
事件“转换”为
CHAR
事件。同样,这听起来非常具体,我找不到如何做。总之,我需要的是将“原始密钥代码”转换为系统“类型化字符”,我也不需要完整的事件

代码示例 显然,我无法编写代码,但这里有一个我想要实现的小例子:

import wx

class TestPanel(wx.Panel):

    def __init__(self, parent):
        super().__init__(parent)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.label = wx.StaticText(self, label="Type something here")
        self.text = wx.TextCtrl(self)
        self.sizer.Add(self.label)
        self.sizer.Add(self.text)
        self.SetSizerAndFit(self.sizer)

        # Binding isn't possible
        #self.text.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)

    def OnKeyDown(self, keycode, unicode=None):
        """
        The `keycode` key was pressed.

        It generated (if anything) the `unicode` character.

        """
        print(f"The {key_code} was pressed, generating the {unicode} character.")

app = wx.App()
frame = wx.Frame(None)
panel = TestPanel(frame)
frame.Show()
app.MainLoop()
这里的挑战是将文本字段连接到
OnKeyDown
方法,在该方法中同时传输密钥代码和unicode密钥。(
EVT\u-key\u-DOWN
上的
GetUnincodeKey()
不起作用,它严格等同于
key\u-code
,这对我没有帮助)


综上所述,如果按键盘上的a键,则键代码应为65(大写a),unicode应为97(小写a),除非caplock处于启用状态。如果使用的布局与QWERTY不同,unicode应始终是文本中显示的字母(此信息仅在
CHAR
事件中给出)。希望澄清!

如果没有代码,有时很难想象您正在尝试做什么。
我认为您缺少的是
event.Skip()

Skip()

此方法可在事件处理程序内使用,以控制在当前事件返回后是否调用绑定到此事件的其他事件处理程序 如果没有Skip(或如果使用Skip(false),将不再处理该事件。如果调用Skip(true),则事件处理系统将继续搜索该事件的其他处理程序函数,即使它已在当前处理程序中处理

此外,从文件中:

GetUnicode密钥(自) 返回与此键事件对应的Unicode字符

如果按下的键没有任何字符值(例如光标键),此方法将返回WXK_NONE。在这种情况下,应使用GetKeyCode检索键的值

因此,我们可以将以下内容绑定到KEY_DOWN、KEY_UP和CHAR:

def EvtKey(self, event):
    if event.GetUnicodeKey():
        print("A value key")
        print(chr(event.GetUnicodeKey()))
    else:
        print("a key event")
        print(event.GetKeyCode())
    event.Skip()
根据您的评论进行编辑: 我建议你看一看,然后
EVT\u CHAR
EVT\u CHAR\u HOOK

import wx

class TestPanel(wx.Panel):

    def __init__(self, parent):
        super().__init__(parent)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.label = wx.StaticText(self, label="Type something here")
        self.text = wx.TextCtrl(self)
        self.sizer.Add(self.label)
        self.sizer.Add(self.text)
        self.SetSizerAndFit(self.sizer)

        self.text.Bind(wx.EVT_CHAR, self.OnKeyDown)
        # The choice here will depend on exactly what you want
        # CHAR_HOOK will additionally give shift, ctrl, alt etc
        #self.text.Bind(wx.EVT_CHAR_HOOK, self.OnKeyDown)

    def OnKeyDown(self, event):
        key_code = event.GetUnicodeKey()
        control_key = event.GetKeyCode()
        if key_code == 0:
            print(f"The control key {control_key} was pressed.")
        else:
            unicode = chr(key_code)
            """
            The `keycode` key was pressed.

            It generated (if anything) the `unicode` character.

            """
            print(f"The {key_code} was pressed, generating the {unicode} character.")
        event.Skip()

app = wx.App()
frame = wx.Frame(None)
panel = TestPanel(frame)
frame.Show()
app.MainLoop()

谢谢你的回答。不幸的是,这并不能解决我的问题。我添加了一个不完整的代码示例,希望这有助于展示我想要实现的目标。@vincent lg我添加了一个替代我原来的答案。非常感谢。我甚至不知道这个事件的存在。我想我需要帮助浏览wxPython的文档。我不确定它是否会存在对我来说是有用的,但这似乎比我考虑的要容易。