wxPython(Phoenix)中有没有 wx.EVT_CHAR 或 event.GetKeyCode() 的等效方法?
我刚开始学习Python,所以尽量不想用Python 2。现在我在用wxPython学习图形用户界面(GUI)元素。Python 3的文档还没有入门部分,所以我在用Python 2的“入门”文档,并在需要的地方转换成Python 3。
我现在在这个部分。这里有一个关于wx.EVT_CHAR的部分,用于处理当焦点对象检测到按键时的事件。我在对比表、CommandEvent文档,以及wx.TextCtrl文档的“这个类发出的事件”部分都没有找到相关的参考。我已经能把大部分其他的非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方法总结中也没有看到GetKeyCode()
的对应方法。
编辑: 问题在Mike Driscoll的帮助下解决了。我实现了他的建议,把这个:
self.Bind(wx.EVT_CHAR, self.OnKeyPress, self.textfield)
改成这个:
self.textfield.Bind(wx.EVT_CHAR, self.OnKeyPress, self.textfield)
另外,我还需要在OnKeyPress
函数中添加e.Skip()
。否则它会记录按键,但不会把文本添加到文本框中。其他事件在不使用Skip()
的情况下也能正常工作,能够将事件传递给控制树中的其他监听器。
1 个回答
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()
你可能还想看看下面这个维基页面,了解不同的绑定方法:
至于你问的另一个问题,虽然我不能确定,但如果在Phoenix里没有OnKeyPress的话,我会非常惊讶。即使文档里没有提到,我也建议你试试看,因为我猜它应该还是有的。