问题描述
我正在尝试使用具有自动完成功能的textCtrl,启用wx.TE_PROCESS_ENTER
并进行选项卡遍历。
如果我禁用wx.TE_PROCESS_ENTER
开关或不执行自动完成,则制表符遍历将起作用。
import wx
import wx.xrc
class MyFrame ( wx.Frame ):
def __init__( self,parent ):
wx.Frame.__init__ ( self,parent,id = wx.ID_ANY,title = wx.EmptyString,pos = wx.DefaultPosition,size = wx.Size( -1,-1 ),style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize,wx.DefaultSize )
Sizer = wx.BoxSizer( wx.VERTICAL )
self.panel = wx.Panel( self,wx.ID_ANY,wx.DefaultPosition,wx.DefaultSize,wx.TAB_TRAVERSAL )
inputSizer = wx.BoxSizer( wx.HORIZONTAL )
self.no_process_enter = wx.TextCtrl( self.panel,wx.EmptyString,0 )
inputSizer.Add( self.no_process_enter,wx.ALL,5 )
self.no_autocomplete = wx.TextCtrl( self.panel,wx.TE_PROCESS_ENTER )
inputSizer.Add( self.no_autocomplete,5 )
self.autocomplete_and_process_enter = wx.TextCtrl( self.panel,wx.TE_PROCESS_ENTER )
inputSizer.Add( self.autocomplete_and_process_enter,5 )
ButtonSizer = wx.StdDialogButtonSizer()
self.ButtonSizerOK = wx.Button( self.panel,wx.ID_OK )
ButtonSizer.AddButton( self.ButtonSizerOK )
self.ButtonSizerCancel = wx.Button( self.panel,wx.ID_CANCEL )
ButtonSizer.AddButton( self.ButtonSizerCancel )
ButtonSizer.Realize();
inputSizer.Add( ButtonSizer,1,wx.EXPAND,5 )
self.panel.SetSizer( inputSizer )
self.panel.Layout()
inputSizer.Fit( self.panel )
Sizer.Add( self.panel,wx.EXPAND |wx.ALL,5 )
self.SetSizer( Sizer )
self.Layout()
self.Fit()
self.Centre( wx.BOTH )
# Connect Events
self.no_process_enter.Bind( wx.EVT_KILL_FOCUS,self.no_process_enterOnKillFocus )
self.no_process_enter.Bind( wx.EVT_SET_FOCUS,self.no_process_enterOnSetFocus )
self.no_process_enter.Bind( wx.EVT_KEY_DOWN,self.OnKeyDown )
self.no_autocomplete.Bind( wx.EVT_KILL_FOCUS,self.no_autocompleteOnKillFocus )
self.no_autocomplete.Bind( wx.EVT_SET_FOCUS,self.no_autocompleteOnSetFocus )
self.no_autocomplete.Bind( wx.EVT_TEXT_ENTER,self.no_autocompleteOnTextEnter )
self.no_autocomplete.Bind( wx.EVT_KEY_DOWN,self.OnKeyDown )
self.autocomplete_and_process_enter.Bind( wx.EVT_KILL_FOCUS,self.autocomplete_and_process_enterOnKillFocus )
self.autocomplete_and_process_enter.Bind( wx.EVT_SET_FOCUS,self.autocomplete_and_process_enterOnSetFocus )
self.autocomplete_and_process_enter.Bind( wx.EVT_TEXT_ENTER,self.autocomplete_and_process_enterOnTextEnter )
self.autocomplete_and_process_enter.Bind( wx.EVT_KEY_DOWN,self.OnKeyDown )
def __del__( self ):
pass
# Virtual event handlers,overide them in your derived class
def no_process_enterOnKillFocus( self,event ):
print('leave no_process_enter\n')
event.Skip()
def no_process_enterOnSetFocus( self,event ):
print('enter no_process_enter')
event.Skip()
def no_autocompleteOnKillFocus( self,event ):
print('leave no_autocomplete\n')
event.Skip()
def no_autocompleteOnSetFocus( self,event ):
print('enter no_autocomplete')
event.Skip()
def no_autocompleteOnTextEnter( self,event ):
print('no_autocomplete - ENTER pressed')
event.Skip()
def autocomplete_and_process_enterOnKillFocus( self,event ):
print('leave autocomplete_and_process_enter\n')
event.Skip()
def autocomplete_and_process_enterOnSetFocus( self,event ):
print('enter autocomplete_and_process_enter')
event.Skip()
def autocomplete_and_process_enterOnTextEnter( self,event ):
print('autocomplete_and_process_enter - ENTER pressed')
event.Skip()
def OnKeyDown( self,event ):
#print(event.GetKeyCode())
if event.GetKeyCode() == wx.WXK_TAB:
print('navigate to next element')
event.EventObject.Navigate()
event.Skip(False)
else:
event.Skip()
if __name__ == '__main__':
app = wx.App()
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show(True)
frame.no_process_enter.AutoComplete(['Hello','World'])
frame.autocomplete_and_process_enter.AutoComplete(['Foo','Bar'])
app.MainLoop()
解决方法
最后,我成功解决了这个问题。技巧是在将事件传递到事件链之前对其进行捕获,并手动进行制表符遍历。
为此,您必须实现TryBefore
方法,并将执行范围限制为无效的文本字段。为了启用双向导航,将参数not event.ShiftDown()
传递给event.EventObject.Navigate
方法。
import wx
import wx.xrc
class MyFrame ( wx.Frame ):
def __init__( self,parent ):
wx.Frame.__init__ ( self,parent,id = wx.ID_ANY,title = wx.EmptyString,pos = wx.DefaultPosition,size = wx.Size( -1,-1 ),style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHints( wx.DefaultSize,wx.DefaultSize )
Sizer = wx.BoxSizer( wx.VERTICAL )
self.panel = wx.Panel( self,wx.ID_ANY,wx.DefaultPosition,wx.DefaultSize,wx.TAB_TRAVERSAL )
inputSizer = wx.BoxSizer( wx.VERTICAL )
self.no_process_enter = wx.TextCtrl( self.panel,wx.EmptyString,0 )
inputSizer.Add( self.no_process_enter,wx.ALL,5 )
self.no_autocomplete = wx.TextCtrl( self.panel,wx.TE_PROCESS_ENTER )
inputSizer.Add( self.no_autocomplete,5 )
self.autocomplete_and_process_enter = wx.TextCtrl( self.panel,wx.TE_PROCESS_ENTER )
inputSizer.Add( self.autocomplete_and_process_enter,5 )
ButtonSizer = wx.StdDialogButtonSizer()
self.ButtonSizerOK = wx.Button( self.panel,wx.ID_OK )
ButtonSizer.AddButton( self.ButtonSizerOK )
self.ButtonSizerCancel = wx.Button( self.panel,wx.ID_CANCEL )
ButtonSizer.AddButton( self.ButtonSizerCancel )
ButtonSizer.Realize();
inputSizer.Add( ButtonSizer,1,wx.EXPAND,5 )
self.panel.SetSizer( inputSizer )
self.panel.Layout()
inputSizer.Fit( self.panel )
Sizer.Add( self.panel,wx.EXPAND |wx.ALL,5 )
self.SetSizer( Sizer )
self.Layout()
self.Fit()
self.Centre( wx.BOTH )
# Connect Events
self.no_process_enter.Bind( wx.EVT_KILL_FOCUS,self.no_process_enterOnKillFocus )
self.no_process_enter.Bind( wx.EVT_SET_FOCUS,self.no_process_enterOnSetFocus )
self.no_autocomplete.Bind( wx.EVT_KILL_FOCUS,self.no_autocompleteOnKillFocus )
self.no_autocomplete.Bind( wx.EVT_SET_FOCUS,self.no_autocompleteOnSetFocus )
self.no_autocomplete.Bind( wx.EVT_TEXT_ENTER,self.no_autocompleteOnTextEnter )
self.autocomplete_and_process_enter.Bind( wx.EVT_KILL_FOCUS,self.autocomplete_and_process_enterOnKillFocus )
self.autocomplete_and_process_enter.Bind( wx.EVT_SET_FOCUS,self.autocomplete_and_process_enterOnSetFocus )
self.autocomplete_and_process_enter.Bind( wx.EVT_TEXT_ENTER,self.autocomplete_and_process_enterOnTextEnter )
def __del__( self ):
pass
def TryBefore(self,event):
if isinstance(event,wx.KeyEvent):
if event.GetEventObject().GetId() in (self.no_autocomplete.GetId(),self.autocomplete_and_process_enter.GetId()):
if event.GetKeyCode() == wx.WXK_TAB:
event.EventObject.Navigate(not event.ShiftDown())
return False
return wx.Frame.TryBefore(self,event)
# Virtual event handlers,overide them in your derived class
def no_process_enterOnKillFocus( self,event ):
print('leave no_process_enter\n')
event.Skip()
def no_process_enterOnSetFocus( self,event ):
print('enter no_process_enter')
event.Skip()
def no_autocompleteOnKillFocus( self,event ):
print('leave no_autocomplete\n')
event.Skip()
def no_autocompleteOnSetFocus( self,event ):
print('enter no_autocomplete')
event.Skip()
def no_autocompleteOnTextEnter( self,event ):
print('no_autocomplete - ENTER pressed')
event.Skip()
def autocomplete_and_process_enterOnKillFocus( self,event ):
print('leave autocomplete_and_process_enter\n')
event.Skip()
def autocomplete_and_process_enterOnSetFocus( self,event ):
print('enter autocomplete_and_process_enter')
event.Skip()
def autocomplete_and_process_enterOnTextEnter( self,event ):
print('autocomplete_and_process_enter - ENTER pressed')
event.Skip()
if __name__ == '__main__':
app = wx.App()
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show(True)
frame.no_process_enter.AutoComplete(['Hello','World'])
frame.autocomplete_and_process_enter.AutoComplete(['Foo','Bar'])
app.MainLoop()