使用基本的wxpython控件工作
专题教程:wxpython中文教程
wxPython 工具包提供了多种不同的窗口部件,包括了本章所提到的基本控件。我们涉及静态文本、可编辑的文本、按钮、微调、滑块、复选框、单选按钮、选择器、列表框、组合框和标尺。对于每种窗口部件,将提供一个关于如何使用它的简短例子,并附上相关的wxPython API 的说明。
显示文本
这一节以在屏幕上显示文本的例子作为开始,包括用作标签的静态文本域,有样式和无样式的都使用了。你可以创建用于用户输入的单行和多行文本域。另外,我们将讨论如何选择文本的字体。
如何显示静态文本?
大概对于所有的UI 工具来说,最基本的任务就是在屏幕上绘制纯文本。在wxPython 中,使用类wx.StaticText 来完成。图7.1显示了这个静态文本控件。
w7.1.gif
在wx.StaticText 中,你能够改变文本的对齐方式、字体和颜色。简单的静态文本控件可以包含多行文本,但是你不能处理多种字体或样式。处理多种字体或样式,要使用更精细的文本控件,如wx.html.HTMLWindow ,它在第十六章中说明。为了在静态文本控件中显示多行文本,我们要包括其中有换行符的字符串,并使控件的大小足够显示所有的文本。有一个特点是你在图7.1中所不能看到的,那就是wx.StaticText 窗口不会接受或响应鼠标事件。
如何显示静态文本
例子7.1显示了产生图7.1的代码。
例7.1 如何使用静态文本的一个基本例子
wx.StaticText 的构造函数和基本的wxWidget 构造函数相同,如下所示:
wx.StaticText(parent, id, label, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name="staticText")
表7.1说明了这些参数——大多数的wxPython 窗口部件都有相类似的参数。对于构造函数的参数的更详细的说明,请参见第2章的相关论述。
表7.1 wx.StaticText 构造函数的参数
parent :父窗口部件。
id :标识符。使用-1可以自动创建一个唯一的标识。
label :你想显示在静态控件中的文本。
pos :一个wx.Point 或一个Python 元组,它是窗口部件的位置。
size :一个wx.Size 或一个Python 元组,它是窗口部件的尺寸。
style :样式标记。
name :对象的名字,用于查找的需要。
接下来我们更详细地讨论样式标记。
使用样式工作
所有在例7.1中静态文本实例所调用的方法都是属于基父类wx.Window 的;wx.StaticText 没有定义任何它自己的新方法。表7.2列出了一些专用于wx.StaticText 的样式。
表7.2
wx.ALIGN_CENTER :静态文本位于静态文本控件的中心。
wx.ALIGN_LEFT :文本在窗口部件中左对齐。这是默认的样式。
wx.ALIGN_RIGHT :文本在窗口部件中右对齐。
wx.ST_NO_AUTORESIZE :如果使用了这个样式,那么在使用了SetLabel() 改变文本之后,静态文本控件不将自我调整尺寸。你应结合使用一个居中或右对齐的控件来保持对齐。
wx.StaticText 控件覆盖了SetLabel() ,以便根据新的文本来调整自身,除非wx.ST_NO_AUTORESIZE 样式被设置了。
当创建了一个居中或右对齐的单行静态文本时,你应该显式地在构造器中设置控件的尺寸。指定尺寸以防止wxPython 自动调整该控件的尺寸。wxPython 的默认尺寸是刚好包容了文本的矩形尺寸,因此对齐就没有什么必要。要在程序中动态地改变窗口部件中的文本,而不改变该窗口部件的尺寸,就要设置wx.ST_NO_AUTORESIZE 样式。这样就防止了在文本被重置后,窗口部件自动调整尺寸到刚好包容了文本。如果静态文本是位于一个动态的布局中,那么改变它的尺寸可能导致屏幕上其它的窗口部件移动,这就对用户产生了干扰。
其它显示文本的技术
还有其它的方法来显示文本。其中之一就是wx.lib.stattext.GenStaticText 类,它是wx.StaticText 的纯Python 实现。它比标准C++版的跨平台性更好,并且它接受鼠标事件。当你想子类化或创建你自己的静态文本控件时,它是更可取的。
你可以使用DrawText(text , x,y) 和DrawRotatedText(text , x, y, angle) 方法直接绘制文本到你的设备上下文。后者是显示有一定角度的文本的最容易的方法,尽管GenStaticText 的子类也能处理旋转问题。设备上下文在第6章中做了简短的说明,我们将在第12章中对它做更详细的说明。
如何让用户输入文本?
超越纯粹显示静态文本,我们将开始讨论当输入文本时的用户交互。wxPython 的文本域窗口部件的类是wx.TextCtrl ,它允许单行和多行文本输入。它也可以作为密码输入控件,掩饰所按下的按键。如果平台支持的话,wx.TextCtrl 也提供丰富格式文本的显示,通过使用所定义和显示的多文本样式。图7.2显示了一个作为单行控件的wx.TextCtrl 的样板。其中的密码输入框对密码进行了掩饰。
w7.2.gif
接下来,我们将演示如何创建文本,然后讨论文本控件的样式选项。
如何创建文本输入控件
例子7.2显示了用于生成图7.2的代码
例7.2 wx.TextCtrl 的单行例子
wx.TextCtrl 类的构造函数较小且比其父类wx.Window 更精细,它增加了两个参数:
wx.TextCtrl(parent , id , value = "", pos =wx.DefaultPosition , size =wx.DefaultSize , style =0, validator =wx.DefaultValidator name =wx.TextCtrlNameStr)
参数parent , id , pos , size , style , 和 name 与wx.Window 构造函数的相同。value 是显示在该控件中的初始文本。
validator 参数用于一个wx.Validator 。validator 通常用于过虑数据以确保只能键入要接受的数据。将在第9章对validator 做更详细的讨论。
使用单行文本控件样式
这里,我们将讨论一些唯一无二的文本控件样式。 表7.3说明了用于单行文本控件的样式标记
表7.3 单行wx.TextCtrl 的样式
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 :控件中的文本右对齐。
像其它样式标记一样,它们可以使用|符号来组合使用,尽管其中的三个对齐标记是相互排斥的。
对于添加文本和移动插入点,该文本控件自动管理用户的按键和鼠标事件。对于该文本控件可用的命令控制组合说明如下:
ctrl -x :剪切 ctrl -c :复制 ctrl -v :粘贴 ctrl -z :撤消
不输入的情况下如何改变文本?
除了根据用户的输入改变显示的文本外,wx.TextCtrl 提供了在程序中改变显示的文本的一些方法。你可以完全改变文本或仅移动插入点到文本中不同的位置。表7.4列出了wx.TextCtrl 的文本处理方法。
表7.4
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() ,只是写入的文本被放置在当前的插入点。
当你的控件是只读的或如果你根据事件而非用户键盘输入来改变控件中的文本是,这些方法是十分有用的。
如何创建一个多行或样式文本控件?
你可以使用wx.TE_MULTILINE 样式标记创建一个多行文本控件。如果本地窗口控件支持样式,那么你可以改变被控件管理的文本的字体和颜色样式,这有时被称为丰富格式文本。对于另外的一些平台,设置样式的调用被忽视掉了。图7.3显示了多行文本控件的一个例子。
w7.3.gif
例7.3包含了用于创建图7.3的代码。通常,创建一个多行文本控件是通过设置wx.TE_MULTILINE 样式标记来处理的。较后的部分,我们将讨论使用丰富文本样式。
例7.3 创建一个多行文本控件
使用多行或丰富文本样式
除了wx.TE_MULTILINE ,还有另外的样式标记,它们只在一个多行或丰富文本控件的上下文中有意义。表7.5列出了这些窗口样式。
表7.5
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 :对于太长的行,以单词为界换行。许多操作系统会忽略该样式。
记住,上面这些样式可以组合使用,所以上面例子中的多行丰富文本控件使用wx.TE_MULTILINE | wx.TE_RICH2 来声明。
用在wx.TextCtrl 窗口部件中的文本样式是类wx.TextAttr 的实例。wx.TextAttr 实例的属性有文本颜色、背景色、和字体,它们都能够在构造函数中被指定,如下所示:
wx.TextAttr(colText , colBack =wx.NullColor , font =wx.NullFont)
文本色和背景色是wxPython 对象,它们可以使用颜色名或颜色的RGB 值(红, 绿, 蓝)来指定。wx.NullColor 指明使用控件目前的背景色。font 是一个wx.Font 对象,我们将在下一小节讨论。wx.NullFont 对象指明使用当前默认字体。
类wx.TextAttr 有相关属性的get *()方法:GetBackgroundColour() , GetFont() , 和 GetTextColour() ,也有返回布尔值的验证存在性的方法:HasBackgroundColour() , HasFont() , 和 HasTextColour() 。如果属性包含一个默认值,则Has *()方法返回False 。如果所有这三个属性都包含默认值,则IsDefault() 方法返回true 。这个类没有set *()方法,因为wx.TextAttr 的实例是不可变的。要改变文本的样式,你必须创建一个实例。
使用文本样式,要调用SetDefaultStyle(style) 或SetStyle(start , end ,style) 。第一个方法设置为控件当前的样式。任何插入到该控件中的文本,不管是键入的,或使用了AppendText() 或 WriteText() 方法的,都以该样式显示。如果样式的某个属性是默认的,那么该样式的当前值被保留。但是,如果样式的所有属性都是默认的,那么恢复默认样式。
SetStyle() 与SetDefaultStyle(style) 类似,只是立即对位于start 和 end 位置之间的文本起作用。样式参数中的默认属性通过检查该控件的当前默认样式来解决。例7.3使用下面一行代码来反转文本中几个字符的颜色:
richText.SetStyle(44 , 52, wx.TextAttr( "white ", "black "))
背景色变为了黑色,相应的字符变为了白色。
表7.6列出了wx.TextCtrl 的方法,它们在处理多行控件和丰富文本中是有用的。
表7.6
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) 相反——指定行和列,返回整数值位置。
如果你能在系统中使用任意字体的话,那么就可以更加灵活的创建样式。 接下来,我们将给你展示如何创建和使用字体实例。
如何创建一个字体?
字体是类wx.Font 的实例。你所访问的任何字体,它已经被安装并对于基本的系统是可访问的。创建一个字体实例,要使用如下的构造函数:
wx.Font(pointSize, family, style, weight, underline=False, faceName="", encoding=wx.FONTENCODING_DEFAULT)
pointSize 是字体的以磅为单位的整数尺寸。family 用于快速指定一个字体而无需知道该字体的实际的名字。字体的准确选择依赖于系统和具体可用的字体。可用的字体类别的示例显示在表7.7中。你所得到的精确的字体将依赖于你的系统。
表7.7
wx.DECORATIVE :一个正式的,老的英文样式字体。
wx.DEFAULT :系统默认字体。
wx.MODERN :一个单间隔(固定字符间距)字体。
wx.ROMAN :serif 字体,通常类似于Times New Roman 。
wx.SCRIPT :手写体或草写体
wx.SWISS :sans -serif 字体,通常类似于Helvetica 或Arial 。
style 参数指明字体的是否倾斜,它的值有:wx.NORMAL , wx.SLANT , 和 wx.ITALIC 。同样,weight 参数指明字体的醒目程度,可选值有:wx.NORMAL , wx.LIGHT ,或wx.BOLD 。这些常量值的行为根据它的名字就可以知道了。underline 参数仅工作在Windows 系统下,如果取值为True ,则加下划线,False 为无下划线。 faceName 参数指定字体名。
encoding 参数允许你在几个编码中选择一个,它映射内部的字符和字本显示字符。编码不是Unicode 编码,只是用于wxPython 的不同的8位编码。大多数情况你可以使用默认编码。
为了获取系统的有效字体的一个列表,并使用户可用它们,要使用专门的类wx.FontEnumerator ,如下所示:
e = wx.FontEnumerator() e.EnumerateFacenames() fontList = e.GetFacenames()
要限制该列表为固定宽度,就要将上面的第一行改为e = wx.FontEnumerator(fixedWidth =True) 。
如果我们系统不支持丰富文本,那么我还能使用样式文本吗?
可以。在wxPython 中有一个跨平台的样式文本窗口部件,名为wx.stc.StyledTextCtrl ,它是Python 对Scintilla 丰富文本组件的封装。因为Scintilla 不是wxWidgets 的一部分,而是作为一个独立的第三方组被合并到了wxPython 中,所以它不与我们已经讨论过的类共享相同的API 。wx.stc.StyledCtrl 的完整说明超过了我们要讲的范围,但是你可以在http: //wiki.wxpython.org /index.cgi /wxStyledTextCtrl 找到相关的文档。
如果我的文本控件不匹配我的字符串该怎么办?
当使用多行wx.TextCtrl 的时候,要知道的一点是,该文本控件是以何种方式存储字符串的。在内部,存储在该wx.TextCtrl 中的多行字符是以n作为行的分隔符的。这与基本的操作系统无关,即使某些系统使用了不同的字符组合作为一行的分隔符。当你使用GetValue() 来获取该字符串时,原来的行分隔符被还原,因此你不必考虑手工转换。这个的好处就是控件中的文本不依赖于任何特定的操作系统。
缺点是,文本控件中的行的长度和行的索引与它们在文本控件外的可能是不同的。例如,如果你在一个Windows 系统上,系统所用的行分隔符是rn,通过GetValue() 所得知的字符串的长度将比通过GetLastPosition() 所得知的字符串的结尾长。通过在例7.3中增加下面两行:
print "getValue ", len(multiText.GetValue()) print "lastPos ", multiText.GetLastPosition()
我们在Unix 系统上所得的结果应该是:
getValue 119 lastPos 119
我们在Windows 系统上所得的结果应该是:
getValue 121 lastPos 119
这意味你不应该使用多行文本控件的位置索引来取得原字符串,位置索引应该用作wx.TextCtrl 的另外方法的参数。对于该控件中的文本的子串,应该使用GetRange() 或GetSelectedText() 。也不要反向索引;不要使用原字符串的索引来取得并放入文本控件中。
例子,它使用了不正确的方法在插入点之后直接得到10个字符:
在Windows 或Mac 系统中要得到正确的结果,最后一行应换为:
selection = text.GetRange(x , x + 10)
如何响应文本事件?
有一个由wx.TextCtrl 窗口部件产生的便利的命令事件,你可能想用它。你需要把相关事件传递给Bind 方法以捕获该事件,如下所示:
frame.Bind(wx.EVT_TEXT , frame.OnText , text)
表7.8说明了这些命令事件。
表7.8 wx.TextCtrl 的事件
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() 指定了该控件的最大长度,那么当用户试图输入更长的字符串时,该事件被触发。你可能会用这个,例如,这时给用户显示一个警告消息。
实例1:
实例2