wxPython - 如何阻止wx.Control失去焦点按箭头键?

时间:2016-07-28 18:21:38

标签: python wxpython wxwidgets

import wx

class Control(wx.Control):

    def __init__(self, parent):

        wx.Control.__init__(self, parent)

        self.Bind(wx.EVT_CHAR, self.OnKey)
        self.Bind(wx.EVT_KEY_DOWN, self.OnKey)
        self.Bind(wx.EVT_KEY_DOWN, self.OnKey)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseClick)

    def OnKey(self, event):
        print("key pressed")
        event.Skip()

    def OnMouseClick(self, event):
        self.SetFocus()
        print("has focus")
        event.Skip()

class Frame(wx.Frame):

    def __init__(self, parent=None):

        wx.Frame.__init__(self, parent)

        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        radio = wx.RadioButton(panel, label="Radio button")
        button = wx.Button(panel, label="Button")
        control = Control(panel)

        sizer.Add(radio, 0, wx.ALL, 5)
        sizer.Add(button, 0, wx.ALL, 5)
        sizer.Add(control, 0, wx.ALL, 5)

        panel.SetSizer(sizer)

        self.Show()

if __name__ == "__main__":
    app = wx.App()
    frame = Frame()
    app.MainLoop() 

一个非常小的例子。

单击控件,将焦点设置为控件。但是,即使将按键绑定到功能OnKey,按箭头键也会将焦点更改为另一个按钮/小部件。

是否有类似于AcceptsFocusFromKeyboard(self)的方法:

  

描述:这个窗口可以通过键盘导航获得焦点吗?如果没有,给它焦点的唯一方法(如果它完全接受它)就是点击它。

除,

我的控件无法从键盘导航中失去焦点的方法

1 个答案:

答案 0 :(得分:0)

你们两个事件处理程序都缺少对:

的调用
event.Skip()

这些事件是非wxCommandEvents,为了使它们正常工作,操作系统必须执行任何需要执行的操作。这就是Skip()的用途。否则该事件将被控件吃掉。

请查看该方法的文档,添加它并查看是否可以解决问题。

另外,出于好奇,当用户按下箭头键时你会发生什么?

如果您希望在按下箭头键时保持焦点,请尝试按event.GetKeyCode()过滤事件(检查文档中是否有正确的函数名称),并且不要在此调用event.Skip()情况下。

如果这不起作用,请尝试捕获wx.EVT_CHAR_HOOK事件。

如果这不起作用,请覆盖FilterEvent()。

另外,你GUI的结构非常奇怪。尝试获取RAD工具(wxGlade,wxSmith等),在那里构建并查看结果。或者查看wxPython发行版中的demo文件夹(可以另外下载),看看如何在wxPython中进行正常的布局。

也可以通过修复GUI来修复箭头键问题。

请尝试使用此代码:

import wx

class Frame(wx.Frame):
    def __init__(self, parent=None):
        wx.Frame.__init__(self, parent)
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        radio = wx.RadioButton(panel, label="Radio button")
        button = wx.Button(panel, label="Button")
        self.Bind(wx.EVT_CHAR, self.OnChar)
        radio.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        button.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseClick)

        sizer.Add(radio, 0, wx.ALL, 5)
        sizer.Add(button, 0, wx.ALL, 5)
        sizer.Add(control, 0, wx.ALL, 5)

        panel.SetSizer(sizer)

        self.Show()

    def OnKeyDown(self, event):
        print("key pressed")
        if not event.GetKeyPress() == wx.WXK_LEFT_ARROW: # Check the function name. I'm writing from memory
            event.Skip()

    def OnChar(self, event):
        print("Character key pressed on the panel")
        event.Skip()

    def OnMouseClick(self, event):
        self.SetFocus()
        print("has focus")
        event.Skip()

if __name__ == "__main__":
    app = wx.App()
    frame = Frame()
    app.MainLoop() 

你应该明白这个想法。仅当按下的键不是箭头键时才调用event.Skip()。