EVT_KILL_FOCUS事件执行后,为什么TextCtrl中闪烁的光标消失了?
After the EVT_KILL_FOCUS event is executed, why does the blinking cursor in TextCtrl disappear?
我有一个 TextCtrl,它有一个 EVT_KILL_FOCUS 事件,我用它来验证字段的内容,在值错误时提醒用户。打开 MessageBox 后,我清除该字段并将焦点设置到我再次验证的字段。问题是应该出现在字段内的文本闪烁光标消失了,我不知道为什么或如何修复它。此行为导致用户不知道焦点位于哪个字段。
有没有人有什么想法?
...
self.txtCode = wx.TextCtrl(self, value='')
self.txtCode.Bind(wx.EVT_KILL_FOCUS, self.__onTxtCodeKillFocus)
self.txtCode.Bind(wx.EVT_CHAR_HOOK, self.__onTxtCodeTabKey)
def __validateTxtCodeContent(self):
if self.txtCode.GetValue() == "":
self.MessageBox(self, "Error Text", _("Warning"))
return False
return True
def __onTxtCodeKillFocus(self, event):
event.Skip()
if self.__validateTxtCodeContent() == False:
self.txtCode.SetValue("")
self.txtCode.SetFocus()
def __onTxtCodeTabKey(self, event):
key = event.GetKeyCode()
shift = event.ShiftDown()
# 9 = TAB, 13 = ENTER
if key != 9 and key != 13:
event.Skip()
return
elif key == 9:
if self.__validateTxtCodeContent():
if shift:
self.btnSave.SetFocus()
else:
self.txtDescription.SetFocus()
else:
self.txtCode.SetValue("")
self.txtCode.SetFocus()
else:
return False
我的验证不仅针对空字段,而且例如只有空字段可以。
重要提示:在 EVT_CHAR_HOOK 事件中也会发生此行为。
我也试过用这个:
self.txtCode.SetValue("")
self.txtCode.SetFocus()
self.txtCode.SetInsertionPointEnd()
self.txtCode.Refresh()
但是效果不是很好
您不能从 KILL_FOCUS
处理程序调用 SetFocus()
。最直接的解决方法是稍后使用 CallAfter()
调用它,但即使这样会 "work",这是一个非常糟糕的主意,因为你不应该阻止用户离开 window - - 无论如何都无法完全阻止它的发生。
只需将代码标记为无效(例如更改其背景),但不要在失去焦点时尝试保持焦点。
P.S。在许多情况下,从焦点事件处理程序调用 MessageBox()
也可能不是一个好主意,最好使用 wxLogWarning()
或 CallAfter()
来延迟显示消息框,直到下一次事件循环迭代。
除了瓦迪姆已经说过的:
您可以在点击 "OK" 按钮或 dialog/panel 即将关闭时进行验证
您可以根据手头的任务使用 wxValidator 来验证用户输入。
我有一个 TextCtrl,它有一个 EVT_KILL_FOCUS 事件,我用它来验证字段的内容,在值错误时提醒用户。打开 MessageBox 后,我清除该字段并将焦点设置到我再次验证的字段。问题是应该出现在字段内的文本闪烁光标消失了,我不知道为什么或如何修复它。此行为导致用户不知道焦点位于哪个字段。
有没有人有什么想法?
...
self.txtCode = wx.TextCtrl(self, value='')
self.txtCode.Bind(wx.EVT_KILL_FOCUS, self.__onTxtCodeKillFocus)
self.txtCode.Bind(wx.EVT_CHAR_HOOK, self.__onTxtCodeTabKey)
def __validateTxtCodeContent(self):
if self.txtCode.GetValue() == "":
self.MessageBox(self, "Error Text", _("Warning"))
return False
return True
def __onTxtCodeKillFocus(self, event):
event.Skip()
if self.__validateTxtCodeContent() == False:
self.txtCode.SetValue("")
self.txtCode.SetFocus()
def __onTxtCodeTabKey(self, event):
key = event.GetKeyCode()
shift = event.ShiftDown()
# 9 = TAB, 13 = ENTER
if key != 9 and key != 13:
event.Skip()
return
elif key == 9:
if self.__validateTxtCodeContent():
if shift:
self.btnSave.SetFocus()
else:
self.txtDescription.SetFocus()
else:
self.txtCode.SetValue("")
self.txtCode.SetFocus()
else:
return False
我的验证不仅针对空字段,而且例如只有空字段可以。
重要提示:在 EVT_CHAR_HOOK 事件中也会发生此行为。
我也试过用这个:
self.txtCode.SetValue("")
self.txtCode.SetFocus()
self.txtCode.SetInsertionPointEnd()
self.txtCode.Refresh()
但是效果不是很好
您不能从 KILL_FOCUS
处理程序调用 SetFocus()
。最直接的解决方法是稍后使用 CallAfter()
调用它,但即使这样会 "work",这是一个非常糟糕的主意,因为你不应该阻止用户离开 window - - 无论如何都无法完全阻止它的发生。
只需将代码标记为无效(例如更改其背景),但不要在失去焦点时尝试保持焦点。
P.S。在许多情况下,从焦点事件处理程序调用 MessageBox()
也可能不是一个好主意,最好使用 wxLogWarning()
或 CallAfter()
来延迟显示消息框,直到下一次事件循环迭代。
除了瓦迪姆已经说过的:
您可以在点击 "OK" 按钮或 dialog/panel 即将关闭时进行验证
您可以根据手头的任务使用 wxValidator 来验证用户输入。