0

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

这是我的测试用例(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()

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

4

2 回答 2

1

对于使用面板作为控件基础的自定义 ComboPopup 控件,我遇到了同样的问题。

EmulateKeypress 刚刚进入了一个永无止境的循环。我发现将面板绑定到 EVT_KEY_DOWN 并将 EVT_CHAR 绑定到覆盖的 OnComboKey​​Event 函数,并在事件处理链中向下跳过事件是在弹出窗口打开的情况下将文本输入到 ComboCtrl 的文本框中所需的全部内容。我认为这是有道理的。由于 Popup 不是严格意义上的控件,因此在通过 Bind() 方法绑定到 wx.app 事件循环之前,它的事件不会属于任何地方。

我在下面包含了重写的 OnComboKey​​Event 函数,以便其他任何人都可以探索这个问题。

 def create(self, *args, **kwds):
       ...
       self.panel.Bind(wx.EVT_CHAR, self.OnComboKeyEvent)
       self.panel.Bind(wx.EVT_KEY_DOWN, self.OnComboKeyEvent)
       ...
 def OnComboKeyEvent(self,  evt):
        evt_dict = {wx.EVT_TEXT.typeId: "TextEvent", 
                            wx.EVT_CHAR.typeId:"CharEvent", 
                            wx.EVT_CHAR_HOOK.typeId:"CharHookEvent",
                            wx.EVT_KEY_UP.typeId:"KeyUpEvent", 
                            wx.EVT_KEY_DOWN.typeId:"KeyDownEvent"}
        if evt.GetEventType() in evt_dict:
            thelogger.debug("oncombokeyevet:%s" % evt_dict[evt.GetEventType()])
        
        super().OnComboKeyEvent(evt)
        evt.Skip()
于 2021-10-21T14:10:27.997 回答
0

我在 wxpython-users 上得到了 Robin Dunn 本人的回答:

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

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

于 2009-01-26T07:46:28.993 回答