【问题标题】:Receiving keystrokes in an opened wx.ComboCtrl在打开的 wx.ComboCtrl 中接收击键
【发布时间】:2010-10-02 15:47:45
【问题描述】:

来自this question,我有一个带有自定义弹出窗口的 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()

编辑:
我发现了这些(未解决的)关于同一主题的讨论..
"ComboCtrl loses keyboard focus when ComboPopup is shown "
"issue using wx.ComboCtrl"

【问题讨论】:

    标签: event-handling wxpython wxwidgets


    【解决方案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()
    

    【讨论】:

      【解决方案2】:

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

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

      它在 非 Windows 平台,但您可以 尝试调用 EmulateKeypress。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-26
        • 2014-11-02
        • 2016-01-15
        • 1970-01-01
        相关资源
        最近更新 更多