【问题标题】:Is there a wx.EVT_CHAR or event.GetKeyCode() equivalent for wxPython( Phoenix )?wxPython( Phoenix ) 是否有 wx.EVT_CHAR 或 event.GetKeyCode() 等效项?
【发布时间】:2014-06-13 15:26:57
【问题描述】:

我刚开始学习 Python,所以我试图避免在 Python 2 中工作太多。目前正在使用 wxPython 学习 GUI 元素。 Python 3 文档还没有介绍部分,因此我使用 Python 2 的“入门”文档并在需要时转换为 Python 3。

我目前在this section。当在焦点对象上检测到按键时,有一个 wx.EVT_CHAR 部分用于事件处理。我在comparison chartCommandEvent docswx.TextCtrl docs 的“此类发出的事件”部分中没有看到对它的引用。我已经能够转换大多数其他非 Python 3 代码,例如 SizerFlags,但我找不到与之等效的代码。

这就是我正在使用的。

import wx
class ExampleFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)
        baseSizer = wx.BoxSizer(wx.VERTICAL)

        # Create an editable text field
        self.textfield = wx.TextCtrl(self)
        # Attach event handlers to text field
        # Event for when the text changes
        self.Bind(wx.EVT_TEXT, self.OnChange, self.textfield)
        # Event for when a key is pressed, for example an arrow key should fire this event but not the EVT_TEXT event
        self.Bind(wx.EVT_CHAR, self.OnKeyPress, self.textfield)

        # Create a button that will clear the textfield
        clearButton = wx.Button(self, wx.ID_CLEAR, "Clear")
        # Attach event handler on the clearButton to call OnClear()
        self.Bind(wx.EVT_BUTTON, self.OnClear, clearButton)

        # Multiline text field for seeing the events fire
        self.logger = wx.TextCtrl(self, -1, style= wx.TE_MULTILINE | wx.TE_READONLY )

        # Add items to frame sizer
        baseSizer.Add(self.textfield, wx.SizerFlags(0).Expand())
        baseSizer.Add(clearButton, wx.SizerFlags(0).Expand())
        baseSizer.Add(self.logger, wx.SizerFlags(1).Expand())

        # Set sizer for frame
        self.SetSizer(baseSizer)

        # Show 
        self.Show()

    def OnClear(self, e):
        # Clear all text entered into the textfield and return focus
        self.textfield.SetValue("")
        self.textfield.SetFocus()

    def OnChange(self, e):
        # Log every time this event is fired
        self.logger.AppendText("OnChange: " + e.GetString() + '\n')

    def OnKeyPress(self, e):
        # Log every key press in the textfield
        self.logger.AppendText("OnKeyPress: " + e.GetKeyCode() + '\n')

app = wx.App(False)
ExampleFrame(None)
app.MainLoop()

OnChange() 将在每次文本字段中的文本更改时触发。 OnKeyPress 永远不会触发。如果我确实让它触发了,我在 CommandEvent methods summary 中看不到 GetKeyCode() 等效项。

编辑: 感谢Mike Driscoll 解决了问题。我实施了他的改变,即改变这一点:

self.Bind(wx.EVT_CHAR, self.OnKeyPress, self.textfield)

对此:

self.textfield.Bind(wx.EVT_CHAR, self.OnKeyPress, self.textfield)  

我还必须将e.Skip() 添加到OnKeyPress 函数中。否则它会记录密钥,但不会将文本添加到文本字段。没有Skip()ing 将事件沿控制树向上传递给其他侦听器,其他事件都很好。

【问题讨论】:

    标签: python events user-interface event-handling wxpython


    【解决方案1】:

    在这种情况下,您只是错误地绑定了事件。你想要

    self.textfield.Bind(wx.EVT_CHAR, self.OnKeyPress, self.textfield)
    

    而不是

    self.Bind(wx.EVT_CHAR, self.OnKeyPress, self.textfield)
    

    这是在上下文中:

    import wx
    class ExampleFrame(wx.Frame):
        def __init__(self, parent):
            wx.Frame.__init__(self, parent)
            baseSizer = wx.BoxSizer(wx.VERTICAL)
    
            # Create an editable text field
            self.textfield = wx.TextCtrl(self)
            # Attach event handlers to text field
            # Event for when the text changes
            self.Bind(wx.EVT_TEXT, self.OnChange, self.textfield)
            # Event for when a key is pressed, for example an arrow key should fire this event but not the EVT_TEXT event
            self.textfield.Bind(wx.EVT_CHAR, self.OnKeyPress, self.textfield)
    
            # Create a button that will clear the textfield
            clearButton = wx.Button(self, wx.ID_CLEAR, "Clear")
            # Attach event handler on the clearButton to call OnClear()
            self.Bind(wx.EVT_BUTTON, self.OnClear, clearButton)
    
            # Multiline text field for seeing the events fire
            self.logger = wx.TextCtrl(self, -1, style= wx.TE_MULTILINE | wx.TE_READONLY )
    
            # Add items to frame sizer
            baseSizer.Add(self.textfield, 1, flag=wx.EXPAND)
            baseSizer.Add(clearButton,0)
            baseSizer.Add(self.logger, 1, flag=wx.EXPAND)
    
            # Set sizer for frame
            self.SetSizer(baseSizer)
    
            # Show 
            self.Show()
    
        def OnClear(self, e):
            # Clear all text entered into the textfield and return focus
            self.textfield.SetValue("")
            self.textfield.SetFocus()
            e.Skip()
    
        def OnChange(self, e):
            # Log every time this event is fired
            self.logger.AppendText("OnChange: " + e.GetString() + '\n')
            e.Skip()
    
        def OnKeyPress(self, e):
            # Log every key press in the textfield
            self.logger.AppendText("OnKeyPress: " + str(e.GetKeyCode()) + '\n')
            e.Skip()
    
    app = wx.App(False)
    ExampleFrame(None)
    app.MainLoop()
    

    您可能需要阅读以下关于不同绑定方法的 wiki 条目:

    至于您的另一个问题,虽然我不能确定,但​​如果凤凰城不存在 OnKeyPress,我会感到非常惊讶。即使它不在文档中,我也会尝试一下,因为我猜它仍然在那里。

    【讨论】:

    • 太棒了。 event.GetKeyCode() 函数在从 EVT_CHAR 事件触发时正常工作。当我尝试输出它以响应 EVT_TEXT 事件时,它抛出了错误。非常感谢关于不同绑定方法的链接。显然,它 WAS 触发了 EVT_CHAR 事件,但该特定事件不会将自身传播到控制树上。所以它在按下一个键时触发,事件得到了满足,但我的听众正在一个永远不会收到它的地方听。出于某种原因,该链接试图将其与有关水果和孩子之类的故事混淆。
    • 是的,这个故事可以帮助一些人理解这个概念……但它并不能帮助所有人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    • 2013-09-29
    相关资源
    最近更新 更多