在打开的wx.ComboCtrl中接收击键

时间:2022-01-21 07:10:58

Coming from this question, I have a wxComboCtrl with a custom popup made of a panel with a bunch of radiobuttons.. My problem is that when I open the popup the combo doesn't get keystrokes, because the events get handled by the panel itself.. I'd like to redirect those KeyEvents to the textctrl of the combo, but I can't find a way to get it to work :/
Am I going the wrong way? Should I manually handle the textctrl value as the user presses keys? I think that would be a bit cumbersome though.. Since supposedly the textctrl already knows how to handle those events..

来自这个问题,我有一个wxComboCtrl,其中一个自定义弹出窗口由一组带有一组radiobuttons的面板组成。我的问题是,当我打开弹出窗口时,组合不会获得击键,因为事件由面板本身处理..我想将这些KeyEvents重定向到组合的textctrl,但我找不到让它工作的方法:/我走错了路?当用户按下键时,我应该手动处理textctrl值吗?我认为这会有点麻烦..因为据说textctrl已经知道如何处理这些事件..

Here's my testcase (wxPython 2.8 on Linux), the "on_key" method should be the culprit:

这是我的测试用例(Linux上的wxPython 2.8),“on_key”方法应该是罪魁祸首:

import wx
import wx.combo

class CustomPopup(wx.combo.ComboPopup):

    def Create(self, parent):
        # Create the popup with a bunch of radiobuttons
        self.panel = wx.Panel(parent)
        sizer = wx.GridSizer(cols=2)
        for x in range(10):
            r = wx.RadioButton(self.panel, label="Element "+str(x))
            r.Bind(wx.EVT_RADIOBUTTON, self.on_selection)
            sizer.Add(r)
        self.panel.SetSizer(sizer)

        # Handle keyevents
        self.panel.Bind(wx.EVT_KEY_UP, self.on_key)

    def GetControl(self):
        return self.panel

    def GetAdjustedSize(self, minWidth, prefHeight, maxHeight):
        return wx.Size(200, 150)

    def on_key(self, evt):
        if evt.GetEventObject() is self.panel:
            # Trying to redirect the key event to the combo.. But this always returns false :(
            print self.GetCombo().GetTextCtrl().GetEventHandler().ProcessEvent(evt)
        evt.Skip()

    def on_selection(self, evt):
        self.Dismiss()
        wx.MessageBox("Selection made")


class CustomFrame(wx.Frame):

    def __init__(self):
        # Toolbar-shaped frame with a ComboCtrl
        wx.Frame.__init__(self, None, -1, "Test", size=(800,50))
        combo = wx.combo.ComboCtrl(self)
        popup = CustomPopup()
        combo.SetPopupControl(popup)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(combo, 0)
        self.SetSizer(sizer)
        self.Layout()

if __name__ == '__main__':
    app = wx.PySimpleApp()
    CustomFrame().Show()
    app.MainLoop()

Edit:
I found these (unresolved) discussions on the same topic..
"ComboCtrl loses keyboard focus when ComboPopup is shown "
"issue using wx.ComboCtrl"

编辑:我在同一主题上发现了这些(未解决的)讨论。“ComboCtrl在显示ComboPopup时丢失键盘焦点”“使用wx.ComboCtrl发出问题”

1 个解决方案

#1


I've got an answer from Robin Dunn himself on wxpython-users:

我在wxpython-users上得到了Robin Dunn自己的回答:

Sending low-level events to native widgets like this does not work the way that most people expect it to. You are expecting this to result in the character being added to the text ctrl,but it can't do that because all that ProcessEvent does is send the wx.Event to any bound event handlers and then it stops. It does not go to the next step and convert that event to the equivalent native message and send it on to the native widget. See the "Simulating keyboard events" thread.

将低级别事件发送到像这样的本机小部件并不像大多数人期望的那样工作。您希望这会导致将字符添加到文本ctrl中,但它不能这样做,因为ProcessEvent所做的就是将wx.Event发送到任何绑定的事件处理程序然后停止。它不会进入下一步并将该事件转换为等效的本机消息并将其发送到本机小部件。请参阅“模拟键盘事件”主题。

It doesn't work especially well on non-Windows platforms, but you could try calling EmulateKeypress instead.

它在非Windows平台上运行效果不佳,但您可以尝试调用EmulateKeypress。

#1


I've got an answer from Robin Dunn himself on wxpython-users:

我在wxpython-users上得到了Robin Dunn自己的回答:

Sending low-level events to native widgets like this does not work the way that most people expect it to. You are expecting this to result in the character being added to the text ctrl,but it can't do that because all that ProcessEvent does is send the wx.Event to any bound event handlers and then it stops. It does not go to the next step and convert that event to the equivalent native message and send it on to the native widget. See the "Simulating keyboard events" thread.

将低级别事件发送到像这样的本机小部件并不像大多数人期望的那样工作。您希望这会导致将字符添加到文本ctrl中,但它不能这样做,因为ProcessEvent所做的就是将wx.Event发送到任何绑定的事件处理程序然后停止。它不会进入下一步并将该事件转换为等效的本机消息并将其发送到本机小部件。请参阅“模拟键盘事件”主题。

It doesn't work especially well on non-Windows platforms, but you could try calling EmulateKeypress instead.

它在非Windows平台上运行效果不佳,但您可以尝试调用EmulateKeypress。