使用基本的控件工作
wxPython 工具包提供了多种不同的窗口部件,包括了本章所提到的基本控件。我们涉及静态文本、可编辑的文本、按钮、微调、滑块、复选框、单选按钮、选择器、列表框、组合框和标尺。对于每种窗口部件,我们将提供一个关于如何使用它的简短例子,并附上相关的wxPython API
显示文本
这一节以在屏幕上显示文本的例子作为开始,包括用作标签的静态文本域,有样式和无样式的都使用了。你可以创建用于用户输入的单行和多行文本域。另外,我们将讨论如何选择文本的字体。
如何显示静态文本?
大概对于所有的UI 工具来说,最基本的任务就是在屏幕上绘制纯文本。在wxPython 中,使用类wx.StaticText
在wx.StaticText 中,你能够改变文本的对齐方式、字体和颜色。简单的静态文本控件可以包含多行文本,但是你不能处理多种字体或样式。处理多种字体或样式,要使用更精细的文本控件,如wx.html.HTMLWindow ,它在第十六章中说明。为了在静态文本控件中显示多行文本,我们要包括其中有换行符的字符串,并使控件的大小足够显示所有的文本。有一个特点是你在图7.1中所不能看到的,那就是wx.StaticText
如何显示静态文本
例子7.1显示了产生图7.1的代码。
例7.1 如何使用静态文本的一个基本例子
import wx
class StaticTextFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Static Text Example',
size=(400, 300))
panel = wx.Panel(self, -1)
# 这是一个基本的静态文本
wx.StaticText(panel, -1, "This is an example of static text",
(100, 10))
# 指定了前景色和背景色的静态文本
rev = wx.StaticText(panel, -1, "Static Text With Reversed Colors",
(100, 30))
rev.SetForegroundColour('white')
rev.SetBackgroundColour('black')
# 指定居中对齐的的静态文本
center = wx.StaticText(panel, -1, "align center", (100, 50),
(160, -1), wx.ALIGN_CENTER)
center.SetForegroundColour('white')
center.SetBackgroundColour('black')
# 指定右对齐的静态文本
right = wx.StaticText(panel, -1, "align right", (100, 70),
(160, -1), wx.ALIGN_RIGHT)
right.SetForegroundColour('white')
right.SetBackgroundColour('black')
# 指定新字体的静态文本
str = "You can also change the font."
text = wx.StaticText(panel, -1, str, (20, 100))
font = wx.Font(18, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
text.SetFont(font)
# 显示多行文本
wx.StaticText(panel, -1, "Your text\ncan be split\n"
"over multiple lines\n\neven blank ones", (20,150))
#显示对齐的多行文本
wx.StaticText(panel, -1, "Multi-line text\ncan also\n"
"be right aligned\n\neven with a blank", (220,150),
style=wx.ALIGN_RIGHT)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = StaticTextFrame()
frame.Show()
app.MainLoop()
wx.StaticText 的构造函数和基本的wxWidget
wx.StaticText(parent, id, label, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name="staticText")
表7.1说明了这些参数——大多数的wxPython
表7.1 wx.StaticText
parent
id
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
你可以使用DrawText(text , x,y) 和DrawRotatedText(text , x, y, angle) 方法直接绘制文本到你的设备上下文。后者是显示有一定角度的文本的最容易的方法,尽管GenStaticText
如何让用户输入文本?
超越纯粹显示静态文本,我们将开始讨论当输入文本时的用户交互。wxPython 的文本域窗口部件的类是wx.TextCtrl ,它允许单行和多行文本输入。它也可以作为密码输入控件,掩饰所按下的按键。如果平台支持的话,wx.TextCtrl 也提供丰富格式文本的显示,通过使用所定义和显示的多文本样式。图7.2显示了一个作为单行控件的wx.TextCtrl
接下来,我们将演示如何创建文本,然后讨论文本控件的样式选项。
如何创建文本输入控件
例子7.2显示了用于生成图7.2的代码
例7.2 wx.TextCtrl
import wx
class TextFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Text Entry Example',
size=(300, 100))
panel = wx.Panel(self, -1)
basicLabel = wx.StaticText(panel, -1, "Basic Control:")
basicText = wx.TextCtrl(panel, -1, "I've entered some text!",
size=(175, -1))
basicText.SetInsertionPoint(0)
pwdLabel = wx.StaticText(panel, -1, "Password:")
pwdText = wx.TextCtrl(panel, -1, "password", size=(175, -1),
style=wx.TE_PASSWORD)
sizer = wx.FlexGridSizer(cols=2, hgap=6, vgap=6)
sizer.AddMany([basicLabel, basicText, pwdLabel, pwdText])
panel.SetSizer(sizer)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = TextFrame()
frame.Show()
app.MainLoop()
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
不输入的情况下如何改变文本?
除了根据用户的输入改变显示的文本外,wx.TextCtrl 提供了在程序中改变显示的文本的一些方法。你可以完全改变文本或仅移动插入点到文本中不同的位置。表7.4列出了wx.TextCtrl
表7.4
AppendText(text)
Clear()
EmulateKeyPress(event)
GetInsertionPoint() SetInsertionPoint(pos) SetInsertionPointEnd()
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包含了用于创建图7.3的代码。通常,创建一个多行文本控件是通过设置wx.TE_MULTILINE
例7.3 创建一个多行文本控件
import wx
class TextFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Text Entry Example',
size=(300, 250))
panel = wx.Panel(self, -1)
multiLabel = wx.StaticText(panel, -1, "Multi-line")
multiText = wx.TextCtrl(panel, -1,
"Here is a looooooooooooooong line of text set in the control.\n\n"
"See that it wrapped, and that this line is after a blank",
size=(200, 100), style=wx.TE_MULTILINE) #创建一个文本控件
multiText.SetInsertionPoint(0) #设置插入点
richLabel = wx.StaticText(panel, -1, "Rich Text")
richText = wx.TextCtrl(panel, -1,
"If supported by the native control, this is reversed, and this is a different font.",
size=(200, 100), style=wx.TE_MULTILINE|wx.TE_RICH2) #创建丰富文本控件
richText.SetInsertionPoint(0)
richText.SetStyle(44, 52, wx.TextAttr("white", "black")) #设置文本样式
points = richText.GetFont().GetPointSize()
f = wx.Font(points + 3, wx.ROMAN, wx.ITALIC, wx.BOLD, True) #创建一个字体
richText.SetStyle(68, 82, wx.TextAttr("blue", wx.NullColour, f)) #用新字体设置样式
sizer = wx.FlexGridSizer(cols=2, hgap=6, vgap=6)
sizer.AddMany([multiLabel, multiText, richLabel, richText])
panel.SetSizer(sizer)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = TextFrame()
frame.Show()
app.MainLoop()
使用多行或丰富文本样式
除了wx.TE_MULTILINE
表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
richText.SetStyle(44 , 52, wx.TextAttr( "white ", "black
背景色变为了黑色,相应的字符变为了白色。
表7.6列出了wx.TextCtrl
表7.6
GetDefaultStyle() SetDefaultStyle(style)
GetLineLength(lineNo)
GetLineText(lineNo)
GetNumberOfLines()
IsMultiLine() IsSingleLine()
PositionToXY(pos)
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
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
为了获取系统的有效字体的一个列表,并使用户可用它们,要使用专门的类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 系统上,系统所用的行分隔符是\r\n,通过GetValue() 所得知的字符串的长度将比通过GetLastPosition()
print "getValue ", len(multiText.GetValue()) print "lastPos ", multiText.GetLastPosition()
我们在Unix
getValue 119 lastPos
我们在Windows
getValue 121 lastPos
这意味你不应该使用多行文本控件的位置索引来取得原字符串,位置索引应该用作wx.TextCtrl 的另外方法的参数。对于该控件中的文本的子串,应该使用GetRange() 或GetSelectedText()
aLongString = """Any old
multi line string
will do here.
Just as long as
it is multiline"""
text = wx.TextCtrl(panel, -1, aLongString, style=wx.TE_MULTILINE)
x = text.GetInsertionPoint()
selection = aLongString[x : x + 10] ### 这将是不正确的
在Windows 或Mac
selection = text.GetRange(x
如何响应文本事件?
有一个由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:
# experiments with wx.StaticText(), set a font for the text
# tested with Python25 and wxPython28 vegaseat 02oct2007
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title, data):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, size=(500, 380))
panel = wx.Panel(self, -1)
# font type: wx.DEFAULT, wx.DECORATIVE, wx.ROMAN, wx.SCRIPT, wx.SWISS, wx.MODERN
# slant: wx.NORMAL, wx.SLANT or wx.ITALIC
# weight: wx.NORMAL, wx.LIGHT or wx.BOLD
#font1 = wx.Font(10, wx.SWISS, wx.ITALIC, wx.NORMAL)
# use additional fonts this way ...
font1 = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Comic Sans MS')
text1 = wx.StaticText(panel, -1, data, pos=(20,15))
text1.SetFont(font1)
# center frame on screen
self.Center()
# show the frame
self.Show(True)
data = """\
Al Gore: The Wild Years
America's Most Popular Lawyers
Career Opportunities for History Majors
Different Ways to Spell "Bob"
Dr. Kevorkian's Collection of Motivational Speeches
Ethiopian Tips on World Dominance
Everything Men Know About Women
Everything Women Know About Men
One Hundred and One Spotted Owl Recipes by the EPA
Staple Your Way to Success
The Amish Phone Book
The Engineer's Guide to Fashion
Ralph Nader's list of pleasures"""
application = wx.PySimpleApp()
# create instance of class MyFrame
window = MyFrame(None, -1, "The World's Shortest Books", data)
# start the event loop
application.MainLoop()
实例2
import wx
if __name__ == "__main__":
app = wx.PySimpleApp()
dialog = wx.FontDialog(None, wx.FontData())
if dialog.ShowModal() == wx.ID_OK:
data = dialog.GetFontData()
font = data.GetChosenFont()
colour = data.GetColour()
print 'You selected: "%s", %d points\n' % (
font.GetFaceName(), font.GetPointSize())
dialog.Destroy()