-
2020-11-26 04:54:41
前言
TextCtrl 是 wxPython 框架里一个非常实用的文本输入控件,我们经常需要对 TextCtrl 做这样一个输入上的约束:只允许输入数字(比如允许 1.2、4.5、100 这些输入而禁止诸如 .8、4t等输入,方便我们在将输入的 str 类型转成 int、float 等其他类型时不需要额外加判断来防止产生异常。今天我查阅 wxPython 的 API,发现了 Validator 这个类可以满足我们的需求。事实上,不仅是满足只允许输入数字这个需要,掌握了 Validator 这个类的使用,我们可以满足任何定制化的需求。
编码
首先必须新建类继承自 wx.Validator
importwxclass MyNumberValidator(wx.Validator):#创建验证器子类
def __init__(self):
wx.Validator.__init__(self)defClone(self):returnMyNumberValidator()def Validate(self,win):#1 使用验证器方法
returnTruedefTransferToWindow(self):returnTruedefTransferFromWindow(self):return True
同时,必须重写 init()(完成初始化)、Clone()(返回当前类的一个实例)等五个方法,你只要把它们当成一个模板就行,然后在此基础上加上我们自己的逻辑。
根据需求加入实现逻辑
importwx#import wx.lib.imagebrowser
class MyNumberValidator(wx.Validator):#创建验证器子类
def __init__(self):
wx.Validator.__init__(self)
self.ValidInput= ['.','0','1','2','3','4','5','6','7','8','9']
self.StringLength=0
self.Bind(wx.EVT_CHAR,self.OnCharChanged)#绑定字符改变事件
defOnCharChanged(self,event):#得到输入字符的 ASCII 码
keycode =event.GetKeyCode()#退格(ASCII 码 为8),删除一个字符。
if keycode == 8:
self.StringLength-= 1
#事件继续传递
event.Skip()return
#把 ASII 码 转成字符
InputChar =chr(keycode)if InputChar inself.ValidInput:#第一个字符为 .,非法,拦截该事件,不会成功输入
if InputChar == '.' and self.StringLength ==0:returnFalse#在允许输入的范围,继续传递该事件。
else:
event.Skip()
self.StringLength+= 1
returnTruereturnFalsedefClone(self):returnMyNumberValidator()def Validate(self,win):#1 使用验证器方法
returnTruedefTransferToWindow(self):returnTruedefTransferFromWindow(self):return True
注意这行代码,self.Bind(wx.EVT_CHAR,self.OnCharChanged) # 绑定字符输入事件,它的意思是,一旦用户输入了字符,该事件会首先交给OnCharChanged方法处理,在OnCharChanged中,特别注意event.Skip()这行代码,它的意思是,过了合法性检验这一关,该事件可以继续传递了,可以交给将该字符加入 textctrl.value 并显示出来的函数处理;否则,事件就在OnCharChanged中被拦截了,不会显示出来,输入失败。
给控件 textctrl 绑定验证器子类。
很简单,只需要在创建 textctrl 的时候加指定关键词参数
wx.TextCtrl(self,validator=MyNumberValidator(),style=wx.TE_CENTER)
style=wx.TE_CENTER 使输入字符居中
再说 Validate() 方法
我们发现,Validator 类中和类名最相似的方法Validate()一直没有使用,其实这个方法是一般使用流程如下,先在 Validate() 方法中加上业务逻辑。
def Validate(self,win):#1 使用验证器方法
print(111)
textCtrl=self.GetWindow()
text=textCtrl.GetValue()
valid_text= ''
for i intext:if i inself.ValidInput:
valid_text+=i
textCtrl.SetValue(valid_text)return True
然后在外部调用它验证合法性
self.n1.GetValidator().Validate(self.n1)
Validate()也可以验证合法性,只不过它不能处理输入事件,必须在输入完成后才能验证合法性,相当于“马后炮”的作用。
完整例子:
#-*- coding: utf-8 -*-#author: inspurer(月小水长)#pc_type lenovo#create_time: 2019/4/12 13:37#file_name: validator.py#github https://github.com/inspurer#qq邮箱 2391527690@qq.com#微信公众号 月小水长(ID: inspurer)
importwx#import wx.lib.imagebrowser
class MyNumberValidator(wx.Validator):#创建验证器子类
def __init__(self):
wx.Validator.__init__(self)
self.ValidInput= ['.','0','1','2','3','4','5','6','7','8','9']
self.StringLength=0
self.Bind(wx.EVT_CHAR,self.OnCharChanged)#绑定字符输入事件
defOnCharChanged(self, event):#得到输入字符的 ASCII 码
keycode =event.GetKeyCode()#退格(ASCII 码 为8),删除一个字符。
if keycode == 8:
self.StringLength-= 1
#事件继续传递
event.Skip()return
#把 ASII 码 转成字符
InputChar =chr(keycode)if InputChar inself.ValidInput:#第一个字符为 .,非法,拦截该事件,不会成功输入
if InputChar == '.' and self.StringLength ==0:returnFalse#在允许输入的范围,继续传递该事件。
else:
event.Skip()
self.StringLength+= 1
returnTruereturnFalsedefClone(self):returnMyNumberValidator()def Validate(self,win):#1 使用验证器方法
print(111)
textCtrl=self.GetWindow()
text=textCtrl.GetValue()
valid_text= ''
for i intext:if i inself.ValidInput:
valid_text+=i
textCtrl.SetValue(valid_text)returnTruedefTransferToWindow(self):returnTruedefTransferFromWindow(self):returnTrueclassGUI(wx.Frame):def __init__(self,parent):
wx.Frame.__init__(self, parent=parent, title="wxPython开发实战",size=(400,300),style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^wx.MAXIMIZE_BOX )
self.Center()
self.SetBackgroundColour('white')
font= wx.Font(16,wx.DECORATIVE, wx.NORMAL, wx.NORMAL)
self.n1= wx.TextCtrl(self,validator=MyNumberValidator(),pos=(100,30),size=(180,45),style=wx.TE_CENTER)
self.n1.SetFont(font)
self.n1.SetBackgroundColour('#95ec69')
self.n1.SetHint('请输入第一个数字')
self.n2= wx.TextCtrl(self,validator=MyNumberValidator(),pos=(100,100),size=(180,45),style=wx.TE_CENTER)
self.n2.SetFont(font)
self.n2.SetBackgroundColour('#95ec69')
self.n2.SetHint('请输入第二个数字')
self.config= wx.Button(self,label="验证输入框一的合法性",pos=(115,170),size=(150,40))
self.config.SetBackgroundColour('#95ec69')
self.Bind(wx.EVT_BUTTON,self.configClicked,self.config)defconfigClicked(self,event):
self.n1.GetValidator().Validate(self.n1)pass
if __name__ == "__main__":
app=wx.App()
GUI(None).Show()
app.MainLoop()
更多相关内容 -
wxPython TextCtrl类
2021-01-30 15:14:13https://www.cnblogs.com/ankier/archive/2012/09/17/2689364.htmlwx.TextCtrl的构造函数 wx.TextCtrl(parent,id,value='',pos=wx.DefaultPostion,size=wx.DefaultSize,style=0,validator=wx.DefaultValidator,name=...https://www.cnblogs.com/ankier/archive/2012/09/17/2689364.html
wx.TextCtrl的构造函数
wx.TextCtrl(parent,
id,
value='',
pos=wx.DefaultPostion,
size=wx.DefaultSize,
style=0,
validator=wx.DefaultValidator,
name=wx.TextCtrlNameStr)
---------------------------------------------------
parent:父窗口部件
id:标识符。使用-1可以自动创建一个唯一的标识。
value:显示的内容
pos:一个wx.Point或一个Python元组,它是窗口部件的位置。
size:一个wx.Size或一个Python元组,它是窗口部件的尺寸。
style:样式标记
validator:赋予textctrl的内容校验器
name:对象的名字,用于查找的需要。
---------------------------------------------------
其中基本样式的取值有:
wx.TE_CENTER:控件中的文本居中。
wx.TE_LEFT:控件中的文本左对齐。默认行为。
wx.TE_NOHIDESEL:文本始终高亮显示,只适用于Windows。
wx.TE_PASSWORD:不显示所键入的文本,代替以星号显示。
wx.TE_PROCESS_ENTER:如果使用了这个样式,那么当用户在控件内按下回车
键时,一个文本输入事件被触发。否则,按键事件内在的由该文本控件或该对话框管
理。
wx.TE_PROCESS_TAB:如果指定了这个样式,那么通常的字符事件在Tab键按下
时创建(一般意味一个制表符将被插入文本)。否则,tab由对话框来管理,通常是
控件间的切换。
wx.TE_READONLY:文本控件为只读,用户不能修改其中的文本。
wx.TE_RIGHT:控件中的文本右对齐。
#-------------------------------------------------------------------------------
# Name: TextCtrlExampleFrame
# Purpose:
#
# Author: ankier
#
# Created: 17/09/2012
# Copyright: (c) ankier 2012
# Licence:
#-------------------------------------------------------------------------------
import wx
class TextCtrlExampleFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, \
"Text ctrl example", pos =(0,0), size =(800, 600))
panel = wx.Panel(self, -1)
#输入文本居中对齐
text = wx.TextCtrl(panel, wx.ID_ANY,pos=(0,30), size =(200, 20), style = wx.TE_CENTER)
#显示密码文本框
text = wx.TextCtrl(panel, wx.ID_ANY, pos=(0,60), size =(200, 20), style = wx.TE_PASSWORD)
#显示只读文本
text = wx.TextCtrl(panel, wx.ID_ANY, pos=(0,90), size =(200, 20), style = wx.TE_READONLY)
def main():
app = wx.PySimpleApp()
frame = TextCtrlExampleFrame()
frame.Show(True)
app.MainLoop()
if __name__ == '__main__':
main()
多行或丰富文本样式有
wx.HSCROLL:如果文本控件是多行的,并且如果该样式被声明了,那么长的行将不会自动换行,并显示水平滚动条。该选项在GTK+中被忽略。
wx.TE_AUTO_URL:如果丰富文本选项被设置并且平台支持的话,那么当用户的鼠标位于文本中的一个URL上或在该URL上敲击时,这个样式将导致一个事件被生成。
wx.TE_DONTWRAP:wx.HSCROLL的别名。
wx.TE_LINEWRAP:对于太长的行,以字符为界换行。某些操作系统可能会忽略该样式。
wx.TE_MULTILINE:文本控件将显示多行。
wx.TE_RICH:用于Windows下,丰富文本控件用作基本的窗口部件。这允许样式文本的使用。
wx.TE_RICH2:用于Windows下,把最新版本的丰富文本控件用作基本的窗口部件。
wx.TE_WORDWRAP:对于太长的行,以单词为界换行。许多操作系统会忽略该样式。
#-------------------------------------------------------------------------------
# Name: TextCtrlExampleFrame
# Purpose:
#
# Author: ankier
#
# Created: 17/09/2012
# Copyright: (c) ankier 2012
# Licence:
#-------------------------------------------------------------------------------
import wx
class TextCtrlExampleFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, \
"Text ctrl example", pos =(0,0), size =(800, 600))
panel = wx.Panel(self, -1)
#多行文本样式
text = wx.TextCtrl(panel, wx.ID_ANY,pos=(0,70), size =(200, 60), style = wx.TE_MULTILINE)
#window下富文本
text = wx.TextCtrl(panel, wx.ID_ANY,pos=(0,140), size =(200, 60), style = wx.TE_RICH)
def main():
app = wx.PySimpleApp()
frame = TextCtrlExampleFrame()
frame.Show(True)
app.MainLoop()
if __name__ == '__main__':
main()
编程下改变文本内容方式有:
AppendText(text):在尾部添加文本。
Clear():重置控件中的文本为“”。并且生成一个文本更新事件。
EmulateKeyPress(event):产生一个按键事件,插入与事件相关联的控制符,就如同实际的按键发生了。
GetInsertionPoint()
SetInsertionPoint(pos)
SetInsertionPointEnd():得到或设置插入点的位置,位置是整型的索引值。控件的开始位置是0。
GetRange(from, to):返回控件中位置索引范围内的字符串。
GetSelection()
GetStringSelection()
SetSelection(from, to):GetSelection()以元组的形式返回当前所选择的文本的起始位置的索引值(开始,结束)。
GetStringSelection()得到所选择的字符串。SetSelection(from, to)设置选择的文本。
GetValue()
SetValue(value):SetValue()改变控件中的全部文本。GetValue()返回控件中所有的字符串。
Remove(from, to):删除指定范围的文本。
Replace(from, to, value):用给定的值替换掉指定范围内的文本。这可以改变文本的长度。
WriteText(text):类似于AppendText(),只是写入的文本被放置在当前的插入点。
#-------------------------------------------------------------------------------
# Name: TextCtrlExampleFrame
# Purpose:
#
# Author: ankier
#
# Created: 17/09/2012
# Copyright: (c) ankier 2012
# Licence:
#-------------------------------------------------------------------------------
import wx
class TextCtrlExampleFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, \
"Text ctrl example", pos =(0,0), size =(800, 600))
panel = wx.Panel(self, -1)
#多行文本样式
self.text = wx.TextCtrl(panel, wx.ID_ANY,pos=(70, 0), size =(200, 60), style = wx.TE_MULTILINE)
button = wx.Button(panel, wx.ID_ANY, pos = (210, 70), size =(100, 20), label = 'Append')
button.Bind(wx.EVT_BUTTON, self.__OnAppendButtonClick)
button = wx.Button(panel, wx.ID_ANY, pos = (110, 70), size =(60, 20), label = 'Clear')
button.Bind(wx.EVT_BUTTON, self.__OnClearClick)
def __OnAppendButtonClick(self, event):
self.text.AppendText("appended text")
def __OnClearClick(self, event):
self.text.Clear()
def main():
app = wx.PySimpleApp()
frame = TextCtrlExampleFrame()
frame.Show(True)
app.MainLoop()
if __name__ == '__main__':
main()
wx.TextCtrl的一些实用的方法:
GetDefaultStyle()
SetDefaultStyle(style):上面已作了说明。
GetLineLength(lineNo):返回给定行的长度的整数值。
GetLineText(lineNo):返回给定行的文本。
GetNumberOfLines():返回控件中的行的数量。对于单行,返回1。
IsMultiLine()
IsSingleLine():布尔类型的方法,确定控件的状态。
PositionToXY(pos):指定文本内的一个整数值位置,返回以元组(列,行)形式的索引位置。列和行的索引值均以0作为开始。
SetStyle(start, end,style):立即改变指定范围内文本的样式。
ShowPosition(pos):引起一个多行控件的滚动,以便观察到指定位置的内容。
XYToPosition(x, y):与PositionToXY(pos)相反——指定行和列,返回整数值位置。
响应文本事件:
frame.Bind(wx.EVT_TEXT, frame.OnText, text)
事件列表如下:
EVT_TEXT:当控件中的文本改变时产生该事件。文本因用户的输入或在程序中使
用SetValue()而被改变,都要产生该事件。
EVT_TEXT_ENTER:当用户在一个wx.TE_PROCESS_ENTER样式的文本控件中
按下了回车键时,产生该事件。
EVT_TEXT_URL:如果在Windows系统上,wx.TE_RICH或wx.TE_RICH2样式被设
置了,并且wx.TE_AUTO_URL样式也被设置了,那么当在文本控件内的URL上发生
了一个鼠标事件时,该事件被触发。
EVT_TEXT_MAXLEN:如果使用SetMaxLength()指定了该控件的最大长度,那么当
用户试图输入更长的字符串时,该事件被触发。你可能会用这个,例如,这时给用户
显示一个警告消息。
-
wxPython控件学习之wx.TextCtrl
2020-11-21 03:18:31wx.TextCtrl的构造函数wx.TextCtrl(parent,id,value='',pos=wx.DefaultPostion,size=wx.DefaultSize,style=0,validator=wx.DefaultValidator,name=wx.TextCtrlNameStr)--------------------------------------------...wx.TextCtrl的构造函数
wx.TextCtrl(parent,
id,
value='',
pos=wx.DefaultPostion,
size=wx.DefaultSize,
style=0,
validator=wx.DefaultValidator,
name=wx.TextCtrlNameStr)
---------------------------------------------------
parent:父窗口部件
id:标识符。使用-1可以自动创建一个唯一的标识。
value:显示的内容
pos:一个wx.Point或一个Python元组,它是窗口部件的位置。
size:一个wx.Size或一个Python元组,它是窗口部件的尺寸。
style:样式标记
validator:赋予textctrl的内容校验器
name:对象的名字,用于查找的需要。
---------------------------------------------------
其中基本样式的取值有:
wx.TE_CENTER:控件中的文本居中。
wx.TE_LEFT:控件中的文本左对齐。默认行为。
wx.TE_NOHIDESEL:文本始终高亮显示,只适用于Windows。
wx.TE_PASSWORD:不显示所键入的文本,代替以星号显示。
wx.TE_PROCESS_ENTER:如果使用了这个样式,那么当用户在控件内按下回车
键时,一个文本输入事件被触发。否则,按键事件内在的由该文本控件或该对话框管
理。
wx.TE_PROCESS_TAB:如果指定了这个样式,那么通常的字符事件在Tab键按下
时创建(一般意味一个制表符将被插入文本)。否则,tab由对话框来管理,通常是
控件间的切换。
wx.TE_READONLY:文本控件为只读,用户不能修改其中的文本。
wx.TE_RIGHT:控件中的文本右对齐。
#-------------------------------------------------------------------------------#Name: TextCtrlExampleFrame#Purpose:#
#Author: ankier#
#Created: 17/09/2012#Copyright: (c) ankier 2012#Licence: #-------------------------------------------------------------------------------
importwxclassTextCtrlExampleFrame(wx.Frame):def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, \"Text ctrl example", pos =(0,0), size =(800, 600))
panel= wx.Panel(self, -1)#输入文本居中对齐
text = wx.TextCtrl(panel, wx.ID_ANY,pos=(0,30), size =(200, 20), style =wx.TE_CENTER)#显示密码文本框
text = wx.TextCtrl(panel, wx.ID_ANY, pos=(0,60), size =(200, 20), style =wx.TE_PASSWORD)#显示只读文本
text = wx.TextCtrl(panel, wx.ID_ANY, pos=(0,90), size =(200, 20), style =wx.TE_READONLY)defmain():
app=wx.PySimpleApp()
frame=TextCtrlExampleFrame()
frame.Show(True)
app.MainLoop()if __name__ == '__main__':
main()
多行或丰富文本样式有
wx.HSCROLL:如果文本控件是多行的,并且如果该样式被声明了,那么长的行将不会自动换行,并显示水平滚动条。该选项在GTK+中被忽略。
wx.TE_AUTO_URL:如果丰富文本选项被设置并且平台支持的话,那么当用户的鼠标位于文本中的一个URL上或在该URL上敲击时,这个样式将导致一个事件被生成。
wx.TE_DONTWRAP:wx.HSCROLL的别名。
wx.TE_LINEWRAP:对于太长的行,以字符为界换行。某些操作系统可能会忽略该样式。
wx.TE_MULTILINE:文本控件将显示多行。
wx.TE_RICH:用于Windows下,丰富文本控件用作基本的窗口部件。这允许样式文本的使用。
wx.TE_RICH2:用于Windows下,把最新版本的丰富文本控件用作基本的窗口部件。
wx.TE_WORDWRAP:对于太长的行,以单词为界换行。许多操作系统会忽略该样式。
#-------------------------------------------------------------------------------#Name: TextCtrlExampleFrame#Purpose:#
#Author: ankier#
#Created: 17/09/2012#Copyright: (c) ankier 2012#Licence: #-------------------------------------------------------------------------------
importwxclassTextCtrlExampleFrame(wx.Frame):def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, \"Text ctrl example", pos =(0,0), size =(800, 600))
panel= wx.Panel(self, -1)#多行文本样式
text = wx.TextCtrl(panel, wx.ID_ANY,pos=(0,70), size =(200, 60), style =wx.TE_MULTILINE)#window下富文本
text = wx.TextCtrl(panel, wx.ID_ANY,pos=(0,140), size =(200, 60), style =wx.TE_RICH)defmain():
app=wx.PySimpleApp()
frame=TextCtrlExampleFrame()
frame.Show(True)
app.MainLoop()if __name__ == '__main__':
main()
编程下改变文本内容方式有:
AppendText(text):在尾部添加文本。
Clear():重置控件中的文本为“”。并且生成一个文本更新事件。
EmulateKeyPress(event):产生一个按键事件,插入与事件相关联的控制符,就如同实际的按键发生了。
GetInsertionPoint()
SetInsertionPoint(pos)
SetInsertionPointEnd():得到或设置插入点的位置,位置是整型的索引值。控件的开始位置是0。
GetRange(from, to):返回控件中位置索引范围内的字符串。
GetSelection()
GetStringSelection()
SetSelection(from, to):GetSelection()以元组的形式返回当前所选择的文本的起始位置的索引值(开始,结束)。
GetStringSelection()得到所选择的字符串。SetSelection(from, to)设置选择的文本。
GetValue()
SetValue(value):SetValue()改变控件中的全部文本。GetValue()返回控件中所有的字符串。
Remove(from, to):删除指定范围的文本。
Replace(from, to, value):用给定的值替换掉指定范围内的文本。这可以改变文本的长度。
WriteText(text):类似于AppendText(),只是写入的文本被放置在当前的插入点。
#-------------------------------------------------------------------------------#Name: TextCtrlExampleFrame#Purpose:#
#Author: ankier#
#Created: 17/09/2012#Copyright: (c) ankier 2012#Licence: #-------------------------------------------------------------------------------
importwxclassTextCtrlExampleFrame(wx.Frame):def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, \"Text ctrl example", pos =(0,0), size =(800, 600))
panel= wx.Panel(self, -1)#多行文本样式
self.text = wx.TextCtrl(panel, wx.ID_ANY,pos=(70, 0), size =(200, 60), style =wx.TE_MULTILINE)
button= wx.Button(panel, wx.ID_ANY, pos = (210, 70), size =(100, 20), label = 'Append')
button.Bind(wx.EVT_BUTTON, self.__OnAppendButtonClick)
button= wx.Button(panel, wx.ID_ANY, pos = (110, 70), size =(60, 20), label = 'Clear')
button.Bind(wx.EVT_BUTTON, self.__OnClearClick)def __OnAppendButtonClick(self, event):
self.text.AppendText("appended text")def __OnClearClick(self, event):
self.text.Clear()defmain():
app=wx.PySimpleApp()
frame=TextCtrlExampleFrame()
frame.Show(True)
app.MainLoop()if __name__ == '__main__':
main()
wx.TextCtrl的一些实用的方法:
GetDefaultStyle()
SetDefaultStyle(style):上面已作了说明。
GetLineLength(lineNo):返回给定行的长度的整数值。
GetLineText(lineNo):返回给定行的文本。
GetNumberOfLines():返回控件中的行的数量。对于单行,返回1。
IsMultiLine()
IsSingleLine():布尔类型的方法,确定控件的状态。
PositionToXY(pos):指定文本内的一个整数值位置,返回以元组(列,行)形式的索引位置。列和行的索引值均以0作为开始。
SetStyle(start, end,style):立即改变指定范围内文本的样式。
ShowPosition(pos):引起一个多行控件的滚动,以便观察到指定位置的内容。
XYToPosition(x, y):与PositionToXY(pos)相反——指定行和列,返回整数值位置。
响应文本事件:
frame.Bind(wx.EVT_TEXT, frame.OnText, text)
事件列表如下:
EVT_TEXT:当控件中的文本改变时产生该事件。文本因用户的输入或在程序中使
用SetValue()而被改变,都要产生该事件。
EVT_TEXT_ENTER:当用户在一个wx.TE_PROCESS_ENTER样式的文本控件中
按下了回车键时,产生该事件。
EVT_TEXT_URL:如果在Windows系统上,wx.TE_RICH或wx.TE_RICH2样式被设
置了,并且wx.TE_AUTO_URL样式也被设置了,那么当在文本控件内的URL上发生
了一个鼠标事件时,该事件被触发。
EVT_TEXT_MAXLEN:如果使用SetMaxLength()指定了该控件的最大长度,那么当
用户试图输入更长的字符串时,该事件被触发。你可能会用这个,例如,这时给用户
显示一个警告消息。
-
解决textctrl控件不实时显示报文信息并且界面会卡住的问题
2022-01-12 10:37:11问题现象描述:textctrl控件不能实时显示报文信息,只能在全部接收之后一次性显示到界面上,当报文信息量较大时,极易造成界面卡死。 原执行界面卡死: 解决办法参考文章:如何从子流程标准输出获得结果并在...问题现象描述:textctrl控件不能实时显示报文信息,只能在全部接收之后一次性显示到界面上,当报文信息量较大时,极易造成界面卡死。
原执行界面卡死:
解决办法参考文章:如何从子流程标准输出获得结果并在TextCtrl中实时显示它们? (Python 2.7 - wxPython)
http://cn.voidcc.com/question/p-faxdrneo-uv.html将textctrl控件显示报文内容的功能移到线程进行执行。
代码片段如下:class LinkThread(Thread): def __init__(self, m_textCtrl1, can_device, baud_rate, device_id): Thread.__init__(self) self.m_textCtrl1 = m_textCtrl1 self.can_device = can_device self.baud_rate = baud_rate self.device_id = device_id self.start() def run(self): Timing0 = can_interface.Timing0_dict[self.baud_rate] Timing1 = can_interface.Timing1_dict[self.baud_rate] vci_initconfig = can_interface.VCI_INIT_CONFIG(0x00000000, 0xFFFFFFFF, 0, 1, Timing0, Timing1, 0) open_state = can_interface.open_device(self.can_device, self.device_id, 0) if open_state == 0: toastone = wx.MessageDialog(None, "打开设备操作失败!", "错误信息提示", wx.YES_DEFAULT | wx.ICON_QUESTION) if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮 toastone.Destroy() # 则关闭提示框 elif open_state == -1: toastone = wx.MessageDialog(None, "USB-CAN设备不存在或USB掉线!", "错误信息提示", wx.YES_DEFAULT | wx.ICON_QUESTION) if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮 toastone.Destroy() # 则关闭提示框 else: # 设置波特率 pData = can_interface.baud_rate_dict[self.baud_rate] can_interface.set_reference(self.can_device, self.device_id, 0, 0, pData) # 初始化can通道 can_interface.ini_can(self.can_device, self.device_id, 0, vci_initconfig) # 启动can设备 start_state = can_interface.start_device(self.can_device, self.device_id, 0) if start_state == 0: toastone = wx.MessageDialog(None, "打开设备操作失败!", "错误信息提示", wx.YES_DEFAULT | wx.ICON_QUESTION) if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮 toastone.Destroy() # 则关闭提示框 elif start_state == -1: toastone = wx.MessageDialog(None, "USB-CAN设备不存在或USB掉线!", "错误信息提示", wx.YES_DEFAULT | wx.ICON_QUESTION) if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮 toastone.Destroy() # 则关闭提示框 else: # 开始接收can报文信息 count = 0 while 1: # while count < 50: # 清空缓冲区 can_interface.clear_buffer(self.can_device, self.device_id, 0) rxdata = can_interface._RX_CAN_OBJ() while can_interface.get_receive_num(self.can_device, self.device_id, 0) == 0: continue # 接收缓存数量 if can_interface.get_receive_num(self.can_device, self.device_id, 0) == 1: if (can_interface.receive_msg(self.can_device, self.device_id, 0, rxdata, 50, 100)): count += 1 msg_view_dict = analysis_msg.analyse_msg(rxdata) msg_view_dict["序号"] = (8 - len(str(count))) * "0" + str(count) text_str = " ".join(["序号:%s" % msg_view_dict["序号"], "传输方向:%s" % msg_view_dict["传输方向"], "帧ID:%s" % msg_view_dict["帧ID"], "帧格式:%s" % msg_view_dict["帧格式"], "帧类型:%s" % msg_view_dict["帧类型"], "数据(HEX):%s" % msg_view_dict["数据(HEX)"]]) self.data = msg_view_dict["数据(HEX)"] wx.CallAfter(self.m_textCtrl1.write, text_str + "\n") else: print("接收缓存区为空") else: print("接收缓存数量大于1")
在原来的Frame下设置按钮触发事件onLink,执行LinkThread线程。
# 设置按钮触发事件 if self.m_button1.GetLabel() == "连接": self.m_button1.Bind(wx.EVT_LEFT_DOWN, self.onLink)
def onLink(self, event): self.link_thread = LinkThread(self.m_textCtrl1, self.can_device, self.baud_rate, self.device_id) if self.link_thread: self.m_button1.SetLabel("断开") self.m_button1.Bind(wx.EVT_LEFT_DOWN, self.onClose)
代码调整之后,textctrl实时显示报文信息并且不会出现界面卡住的运行截图:
-
如何编写wxPython textCtrl焦点事件
2021-07-16 13:07:34I'm trying to fire a line of code when the user clicks on a textCtrl. The end goal is to highlight the contents of the box when it is clicked on. I am aware that this is possible with wx.EVT_SET_FOCUS... -
wxpython中Textctrl回车事件无效的解决方法
2020-12-25 06:43:02本文实例讲述了wxpython中Textctrl回车事件无效的解决方法。分享给大家供大家参考,具体如下: 今天使用wxptyhon的Textctrl控件开发客户端时遇到了一个问题, 按照HTML表单的逻辑, 我们在Textctrl里回车应该提交查询,... -
wxPython控件学习之TextCtrl(一)单行文本框
2020-11-21 03:18:31wxPython控件学习之TextCtrl(一)单行文本框 代码如下:#!/usr/bin/env python#coding:UTF-8'''Created on 2010-5-14wxPython的文本输入控件(wx.TextCtrl)操作范例@author: zyl508@gmail.... -
wxPython控件学习之TextCtrl(二)多行及样式文本框
2020-12-17 15:49:19wx.Frame.__init__(self,None,-1,"Example For MultiTextCtrl", size=(300,250)) panel=wx.Panel(self,-1) #普通多行文本输入框 multiLabel=wx.StaticText(panel,-1,"Multi-Line:") multiText=wx.TextCtrl(panel,-1... -
wxPython控件学习之TextCtrl(三)响应文本控件事件
2020-12-17 15:49:37frame.Bind(wx.EVT_TEXT, frame.OnText, text)TextCtrl支持的事件类型:-----------------------------------------------------------------EVT_TEXT:文本因用户的输入或在程序中使用SetValue()而被改变,都要产生... -
如何制作wxpython密码textctrl show chars?
2020-11-26 04:54:39sizer= wx.BoxSizer(wx.HORIZONTAL) self.text_password= wx.TextCtrl(panel,style=wx.TE_PASSWORD) self.password_sizer.Add(self.text_password,0,wx.ALL,5) self.text_no_password= wx.TextCtrl(panel) self.text... -
WxPython[TextCtrl]:使用TextCtrl函数将光标定位到文本末尾的方法。
2021-04-28 02:26:52screen_text() self.write = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE, value=self.message) System_Checkup = wx.Button(panel, 1, label='System_Checkup') Open_the_Web = wx.Button(panel, 1, label=' ... -
如何从wxpython中的textctrl接受值
2020-11-26 04:54:35请帮助我进行修改,以便在按下按钮时需要将在textctrl中输入的字符串用户存储到变量中.#! /usr/bin/env python#Boa:Frame:Frame1import wxdef create(parent):return Frame1(parent)[wxID_FRAME1, wxID_FRAME1BUTTON1... -
如何获取在wxpython中循环期间创建的TextCtrl值
2020-12-29 04:06:05'low'] for item in ticker_items: sizer.Add(wx.TextCtrl(self, value=item, size=(-1, -1), name=item) ) btn = wx.Button(self, label="Update") btn.Bind(wx.EVT_BUTTON, self.updateTextCtrls) sizer.Add(btn)... -
wxPython 第五篇、使用TextCtrl、Button写的Log in 实例讲解
2019-11-10 18:26:43wxPython 第五篇、使用TextCtrl、Button写的Log in 实例讲解 前言: wxPython有很多控件例如Button、CheckBox、StaticText、ListBox 等等(and so on),它的控件还是很多的,可以满足基本的开发需要,但是一天是... -
Wxpython textctrl索引位置错乱,换行符问题
2021-12-18 10:47:34在Textctrl中输入带有换行的文本,通过自定义的搜索函数,会出现索引错误的问题,以下是我的原来的代码 def search_text(self, event): print('搜索文本!') keyword = event.GetString() if keyword == self.pre... -
python文本输入控件wx.TextCtrl用法举例
2020-12-04 01:02:56在python中如何使用文本输入控件wx.TextCtrl进行编程,本节做下分享。构造函数: 代码示例:wx.TextCtrl(parent,id,value='',pos=wx.DefaultPostion,size=wx.DefaultSize,style=0,validator=wx.DefaultValidator,name... -
wxpython控件TextCtrl如何显示多行文本
2022-01-07 13:55:21选择TextCtrl的style为“wxTE_MULTILIME"即设置TextCtrl为显示多行文本。 或者直接修改代码: -
WxPython [TextCtrl]:使用TextCtrl函数将光标定位到文本结尾的方式。
2020-11-25 23:04:22很高兴认识你。我有一个关于使用wxpython的...WxPython [TextCtrl]:使用TextCtrl函数将光标定位到文本结尾的方式。#!/usr/bin/pythonimport wxdef get_main_screen_text():text = "\n [Anyfusion Monitoring Syst... -
wxpython学习笔记之wx.TextCtrl
2020-07-29 16:15:23",size=(150,-1)) t1.SetInsertionPoint(0) st2 = wx.StaticText(panel, -1, "Password:") t2 = wx.TextCtrl(panel, -1, "”password", size=(150, -1),style=wx.TE_PASSWORD) sizer = wx.FlexGridSizer(cols=2, ... -
使用 wx.TextCtrl 实现登录界面
2021-02-12 12:18:31代码如下: import wx ... wx.Frame.__init__(self,parent,id,title='创建TextCtrl类',size=(400,300)) panel=wx.Panel(self) self.title=wx.StaticText(panel,label='请输入用户名和密码',pos=(140,20)) -
RuntimeError: wrapped C/C++ object of type TextCtrl has been deleted
2020-07-30 17:51:29在接收部分出现问题,接收到的代码,应如何插入到只读文本中,使用AppendText()出现RuntimeError: wrapped C/C++ object of type TextCtrl has been deleted错误 应该怎么解决 试着在self.log1.AppendText()前... -
如何从wxPython中的wx.TextCtrl控件获取滚动位置/范围
2020-12-17 15:49:18Okay, so here's where I've got to:import wxfrom threading import Timerimport timeclass Form1(wx.Panel):def __init__(self, parent):wx.Panel.__init__(self, parent)self.logger = wx.TextCtrl(self,5, "",wx...