使用按钮工作
在wxPython 中有很多不同类型的按钮。这一节,我们将讨论文本按钮、位图按钮、开关按钮(toggle buttons )和通用(generic )按钮。
如何生成一个按钮?
在第一部分(part 1)中,我们已经说明了几个按钮的例子,所以这里我们只简短的涉及它的一些基本的东西。图7.4显示了一个简单的按钮。
图7.4
使用按钮是非常简单的。例7.4显示了该简单按钮的代码。
- import wx
- class ButtonFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Button Example',
- size=(300, 100))
- panel = wx.Panel(self, -1)
- self.button = wx.Button(panel, -1, "Hello", pos=(50, 20))
- self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
- self.button.SetDefault()
- def OnClick(self, event):
- self.button.SetLabel("Clicked")
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- frame = ButtonFrame()
- frame.Show()
- app.MainLoop()
wx.Button 的构造函数类似于我们已经看到过的,如下所示:
wx.Button(parent , id , label , pos , size =wxDefaultSize , style =0, validator , name ="button ")
参数label 是显示在按钮上的文本。它可以在程序运行期间使用SetLabel() 来改变,并且使用GetLabel() 来获取。另外两个有用的方法是GetDefaultSize() 和SetDefault() 。GetDefaultSize() 返回系统默认按钮的尺寸(对于框架间的一致性是有用的);SetDefault() 设置按钮为对话框或框架的默认按钮。默认按钮的绘制不同于其它按钮,它在对话框获得焦点时,通常按下回车键被激活。
wx.Button 类有一个跨平台的样式标记:wx.BU_EXACTFIT 。如果定义了这个标记,那么按钮就不把系统默认的尺寸作为最小的尺寸,而是把能够恰好填充标签的尺寸作为最小尺寸。如果本地窗口部件支持的话,你可以使用标记wx.BU_LEFT , wx.BU_RIGHT , wx.BU_TOP , 和 wx.BU_BOTTOM 来改变按钮中标签的对齐方式。每个标记对齐标签到边,该边你根据标记的名字可以知道。正如我们在第一部分中所讨论过的,wx.Button 在被敲击时触发一个命令事件,事件类型是EVT_BUTTON 。
如何生成一个位图按钮?
有时候,你可能想在你的按钮上显示一个图片,而非一个文本标签,如图7.5所示。
在wxPython 中,使用类wx.BitmapButton 来创建一个位图按钮。处理一个wx.BitmapButton 的代码是与通用按钮的代码非常类似的,例7.5显示了产生7.5的代码。
例7.5 创建一个位图按钮
- import wx
- class BitmapButtonFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Bitmap Button Example',
- size=(200, 150))
- panel = wx.Panel(self, -1)
- bmp = wx.Image("bitmap.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
- self.button = wx.BitmapButton(panel, -1, bmp, pos=(10, 20))
- self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
- self.button.SetDefault()
- self.button2 = wx.BitmapButton(panel, -1, bmp, pos=(100, 20),
- style=0)
- self.Bind(wx.EVT_BUTTON, self.OnClick, self.button2)
- def OnClick(self, event):
- self.Destroy()
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- frame = BitmapButtonFrame()
- frame.Show()
- app.MainLoop()
与普通按钮的主要的区别是你需要提供一个位图,而非一个标签。否则,构造器和大部分代码是与文本按钮的例子相同的。位图按钮在被敲击时同样产生EVT_BUTTON 事件。
关于位图按钮有几个有趣的特性。首先,一个样式标记wx.BU_AUTODRAW ,它是默认的。如果该标记是打开的,那么位图将带有一个3D的边框,这使它看起来像一个文本按钮(图7.5中的左按钮),并且按钮比原位图大几个像素。如果该标记是关闭的,则位图被简单地绘制为按钮而没有边框。通过设置style =0使图7.5中右边的按钮关闭默认设置,它没有了3D的效果。
默认情况下,给wxPython 传递单个位图作为主显示的位图,在当按钮被按下或获得焦点或无效时,wxPython 自动创建一个标准的派生自主显示的位图的位图作为此时显示在按钮上的位图。如果自动创建的位图不是你想要的,你可以使用下面的方法: SetBitmapDisabled() , SetBitmapFocus() ,SetBitmapLabel() , 和SetBitmap -Selected()显式地告诉wxPython 你要使用哪个位图。这些方法都要求一个wx.Bitmap 对象作为参数,并且它们都有相应的get*()方法。
你不能通过使用标准的wxWidgets C++库来合并一个位图和文本。你可以创建一个包含文本的位图。然而,正如我们将在通用按钮问题讨论中所看到的,wxPython 有额外的方法来实现这一合并行为。
=== 如何创建开关按钮(toggle button )?===
你可以使用wx.ToggleButton 创建一个开关按钮(toggle button )。开关按钮(toggle button )看起来十分像文本按钮,但它的行为更像复选框,它的选择或非选择状态是可视化的。换句话说,当你按下一个开关按钮(togglebutton )时,它将一直保持被按下的状态直到你再次敲击它。
在wx.ToggleButton 与父类wx.Button 之间只有丙个区别:
1、当被敲击时,wx.ToggleButton 发送一个EVT_TOGGLEBUTTON 事件。
2、wx.ToggleButton 有GetValue() 和SetValue() 方法,它们处理按钮的二进制状态。
开关按钮(toggle button )是有用的,它相对于复选框是另一好的选择,特别是在工具栏中。记住,你不能使用wxWidgets 提供的对象来将开关按钮(toggle button )与位图按钮合并,但是wxPython 有一个通用按钮类,它提供了这种行为,我们将在下一节对其作讨论。
什么是通用按钮,我为什么要使用它?
通用按钮是一个完全用Python 重新实现的一个按钮窗口部件,回避了本地系统窗口部件的用法。它的父类是wx.lib.buttons. GenButton 。通用按钮有通用位图和切换按钮。
这儿有几个使用通用按钮的原因:
1、通用按钮比本地按钮具有更好的跨平台的外观。另一方面,通用按钮可能在具体的系统上看起来与本地按钮有些微的不同。
2、使用通用按钮,你对它的外观有更多的控制权,并且能改变属性,如3D斜面的宽度和颜色,而这对于本地控件可能是不允许的。
3、通用按钮类允许特性的合并,而wxWidget 按钮不行。比如GenBitmapTextButton 允许文本标签和位图的组合,GenBitmapToggleButton 实现一个位图切换按钮。
4、如果你正在创建一个按钮类,使用通用按钮是较容易的。由于其代码和参数是用Python 写的,所以当创建一个新的子类的时候,对于检查和覆盖,它们的可用性更好。
图7.6显示了实际的通用按钮和常规按钮的对照。
图7.6
例7.6显示了产生图7.6的代码。第二个导入语句:import wx.lib.buttons as buttons ,是必须的,它使得通用按钮类可用。
例7.6 创建和使用wxPython 的通用按钮
- import wx
- import wx.lib.buttons as buttons
- class GenericButtonFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Generic Button Example',
- size=(500, 350))
- panel = wx.Panel(self, -1)
- sizer = wx.FlexGridSizer(1, 3, 20, 20)
- b = wx.Button(panel, -1, "A wx.Button")
- b.SetDefault()
- sizer.Add(b)
- b = wx.Button(panel, -1, "non-default wx.Button")
- sizer.Add(b)
- sizer.Add((10,10))
- b = buttons.GenButton(panel, -1, 'Genric Button')#基本的通用按钮
- sizer.Add(b)
- b = buttons.GenButton(panel, -1, 'disabled Generic')#无效的通用按钮
- b.Enable(False)
- sizer.Add(b)
- b = buttons.GenButton(panel, -1, 'bigger')#自定义尺寸和颜色的按钮
- b.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.BOLD, False))
- b.SetBezelWidth(5)
- b.SetBackgroundColour("Navy")
- b.SetForegroundColour("white")
- b.SetToolTipString("This is a BIG button...")
- sizer.Add(b)
- bmp = wx.Image("bitmap.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
- b = buttons.GenBitmapButton(panel, -1, bmp)#通用位图按钮
- sizer.Add(b)
- b = buttons.GenBitmapToggleButton(panel, -1, bmp)#通用位图开关按钮
- sizer.Add(b)
- b = buttons.GenBitmapTextButton(panel, -1, bmp, "Bitmapped Text",
- size=(175, 75))#位图文本按钮
- b.SetUseFocusIndicator(False)
- sizer.Add(b)
- b = buttons.GenToggleButton(panel, -1, "Toggle Button")#通用开关按钮
- sizer.Add(b)
- panel.SetSizer(sizer)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- frame = GenericButtonFrame()
- frame.Show()
- app.MainLoop()
在例7.6中,通用按钮的用法非常类似于常规按钮。通用按钮产生与常规按钮同样的EVT_BUTTON 和EVT_TOGGLEBUTTON 事件。通用按钮引入了GetBevelWidth() 和SetBevelWidth() 方法来改变3D斜面效果。它们用在了图7.6中大按钮上。
通用位图按钮类GenBitmapButton 工作的像标准的wxPython 版本。在构造器中。GenBitmapTextButton 要求先要一个位图,然后是文本。通用类GenToggleButton ,GenBitmapToggleButton ,和 GenBitmapTextToggleButton 与非开关版的一样,并且对于处理按钮的开关状态响应于GetToggle() 和 SetToggle() 。
在下一节,我们将讨论关于使你的用户能够输入或观看一个数字值的方案。
输入并显示数字
有时你想要显示图形化的数字信息,或你想让用户不必使用键盘来输入一个数字量。在这一节,我们将浏览wxPython 中用于数字输入和显示的工具:滑块(slider )、微调控制框和显示量度的标尺。
如何生成一个滑块?
滑块是一个窗口部件,它允许用户通过在该控件的尺度内拖动指示器来选择一个数值。在wxPython 中,该控件类是wx.Slider ,它包括了滑块的当前值的只读文本的显示。图7.7显示了水平和垂直滑块的例子。
图7.7
滑块的基本使用是十分简单的,但是你可以增加许多事件。
如何使用滑块
例7.7是产生图7.7的例子。
例7.7 水平和垂直滑块的显示代码
- import wx
- class SliderFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Slider Example',
- size=(300, 350))
- panel = wx.Panel(self, -1)
- self.count = 0
- slider = wx.Slider(panel, 100, 25, 1, 100, pos=(10, 10),
- size=(250, -1),
- style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
- slider.SetTickFreq(5, 1)
- slider = wx.Slider(panel, 100, 25, 1, 100, pos=(125, 70),
- size=(-1, 250),
- style=wx.SL_VERTICAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
- slider.SetTickFreq(20, 1)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- frame = SliderFrame()
- frame.Show()
- app.MainLoop()
通常,当你使用wx.Slider 类时,所有你所需要的就是一个构造函数,它与别的调用不同,如下所示:
wx.Slider(parent , id , value , minValue , maxValue , pos =wxDefaultPosition , size =wx.DefaultSize , style=wx.SL_HORIZONTAL , validator =wx.DefaultValidator , name ="slider ")
value 是滑块的初始值,而minValue 和maxValue 是两端的值。
使用滑块样式工作
滑块的样式管理滑块的位置和方向,如下表7.9所示。
表7.9 wx.Slider 的样式
wx.SL_AUTOTICKS :如果设置这个样式,则滑块将显示刻度。刻度间的间隔通过SetTickFreq 方法来控制。
wx.SL_HORIZONTAL :水平滑块。这是默认值。
wx.SL_LABELS :如果设置这个样式,那么滑块将显示两头的值和滑块的当前只读值。有些平台可能不会显示当前值。
wx.SL_LEFT :用于垂直滑块,刻度位于滑块的左边。
wx.SL_RIGHT :用于垂直滑块,刻度位于滑块的右边。
wx.SL_TOP :用于水平滑块,刻度位于滑块的上部。
wx.SL_VERTICAL :垂直滑块。
如果你想通过改变滑块中的值来影响你的应用程序中的其它的部分,那么这儿有几个你可使用的事件。这些事件与窗口滚动条所发出的是相同的,详细的说明参见第8章的滚动条部分。
表7.10列出了你可用于滑块的Set *()方法。每个Set *()方法都有一个对应的Get 方法——Get 方法的描述参考其对应的Set *()方法。
表7.10
GetRange() SetRange(minValue , maxValue) :设置滑块的两端值。
GetTickFreq() SetTickFreq(n , pos) :使用参数n设置刻度的间隔。参数pos 没有被使用,但是它仍然是必要的,将它设置为1。
GetLineSize() SetLineSize(lineSize) :设置你每按一下方向键,滑块所增加或减少的值。
GetPageSize() SetPageSize(pageSize) :设置你每按一下PgUp 或PgDn 键,滑块所增加或减少的值。
GetValue() SetValue(value) :设置滑块的值。
尽管滑块提供了一个可能范围内的值的快速的可视化的表示,但是它们也有两个缺点。其一是它们占据了许多的空间,另外就是使用鼠标精确地设置滑块是困难的。下面我们将讨论的微调控制器解决了上面的这两个问题。
如何得到那些灵巧的上下箭头按钮?
微调控制器是文本控件和一对箭头按钮的组合,它用于调整数字值,并且在你要求一个最小限度的屏幕空间的时候,它是替代滑块的最好选择。图7.8显示了wxPython 的微调控制器控件。
图7.8
在wxPython 中,类wx.SpinCtrl 管理微调按钮和相应的文本显示。在接下来的部分,我们将创建一个微调控制器。
如何创建一个微调控制器
要使用wx.SpinCtrl 来改变值,可通过按箭头按钮或通过在文本控件中输入。键入的非数字的文本将被忽略,尽管控件显示的是键入的非数字的文本。一个超出范围的值将被认作是相应的最大或最小值,尽管显示的是你输入的值。例7.8显示了wx.SpinCtrl 的用法。
例7.8 使用wx.SpinCtrl
- import wx
- class SpinnerFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Spinner Example',
- size=(100, 100))
- panel = wx.Panel(self, -1)
- sc = wx.SpinCtrl(panel, -1, "", (30, 20), (80, -1))
- sc.SetRange(1,100)
- sc.SetValue(5)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- SpinnerFrame().Show()
- app.MainLoop()
几乎微调控件所有复杂的东西都是在其构造函数中,其构造函数如下:
- wx.SpinCtrl(parent, id=-1, value=wx.EmptyString, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.SP_ARROW_KEYS, min=0, max=100, initial=0, name="wxSpinCtrl")
参数value 是虚设的。使用initial 参数来设置该控件的值,并使用min 和max 来设置该控件的范围。
对于wx.SpinCtrl 有两个样式标记。默认样式是wx.SP_ARROW_KEYS ,它允许用户通过键盘上的上下箭头键来改变控件的值。样式wx.SP_WRAP 使得控件中的值可以循环改变,也就是说你通过箭头按钮改变控件中的值到最大或最小值时,如果再继续,值将变为最小或最大,从一个极端到另一个极端。
你也可以捕获EVT_SPINCTRL 事件,它在当控件的值改变时产生(即使改变是直接由文本输入引起的)。如果文本改变了,将引发一个EVT_TEXT 事件,就如同你使用一个单独的文本控件时一样。
如例7.8所示,你可以使用SetRange(minVal , maxVal) 和 SetValue(value) 方法来设置范围和值。SetValue() 函数要求一个字符串或一个整数。要得到值,使用方法:GetValue() (它返回一个整数), GetMin() , 和 GetMax() 。
当你需要对微调控制器的行为有更多的控制时,如允许浮点数或一个字符串的列表,你可以把一个wx.SpinButton和一个wx.TextCtrl 放到一起,并在它们之间建立一个联系。然后捕获来自wx.SpinButton 的事件,并更新wx.TextCtrl 中的值。
如何生成一个进度条?
如果你只想图形化地显示一个数字值而不允许用户改变它,那么使用相应的wxPython 窗口部件wx.Gauge 。 相关的例子就是图7.9所显示的进度条。
图7.9
例7.9显示了产生图7.9的代码。与本章中许多别的例子不同的是,这里我们增加了一个事件处理器。下面的代码在空闭时调整标尺的值,使得值周而复始的变化。
例7.9 显示并更新一个wx.Gauge
- import wx
- class GaugeFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Gauge Example',
- size=(350, 150))
- panel = wx.Panel(self, -1)
- self.count = 0
- self.gauge = wx.Gauge(panel, -1, 50, (20, 50), (250, 25))
- self.gauge.SetBezelFace(3)
- self.gauge.SetShadowWidth(3)
- self.Bind(wx.EVT_IDLE, self.OnIdle)
- def OnIdle(self, event):
- self.count = self.count + 1
- if self.count == 50:
- self.count = 0
- self.gauge.SetValue(self.count)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- GaugeFrame().Show()
- app.MainLoop()
wx.Gauge 的构造函数类似于其它的数字的窗口部件:
- wx.Gauge(parent, id, range, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.GA_HORIZONTAL, validator=wx.DefaultValidator, name="gauge")
当你使用参数range 来指定数字值时,该值代表标尺的上限,而下限总是0。默认样式wx.GA_HORIZONTAL 提供了一个水平条。要将它旋转90度,使用wx.GA_VERTICAL 样式。如果你是在Windows 上,那么样式wx.GA_PROGRESSBAR 给你的是来自Windows 工具包的本地化的进度条。
作为一个只读控件,wx.Gauge 没有事件。然而,它的属性你可以设置。你可以使用GetValue() , Set -Value(pos) ,GetRange() , 和 SetRange(range) 来调整它的值和范围。如果你是在Windows 上,并且没有使用本地进度条样式,那么你可以使用SetBezelFace(width) and SetShadowWidth() 来改变3D效果的宽度。
给用户以选择
几乎每个应用程序都要求用户在一套预先定义的选项间进行选择。在wxPython 中,有多种窗口部件帮助用户处理这种任务,包括复选框、单选按钮、列表框和组合框。接下来的部分将介绍这些窗口部件。
如何创建一个复选框?
复选框是一个带有文本标签的开关按钮。复选框通常成组的方式显示,但是每个复选框的开关状态是相互独立的。当你有一个或多个需要明确的开关状态的选项时,可以使用复选框。图7.10显示了一组复选框。
图7.10
在wxPython 中复选框很容易使用。它们是wx.CheckBox 类的实例,并且通过把它们一起放入一个父容器中可以让它们在一起显示。例7.10提供了生成图7.10的代码。
例7.10 插入三个复选框到一个框架中
- import wx
- class CheckBoxFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Checkbox Example',
- size=(150, 200))
- panel = wx.Panel(self, -1)
- wx.CheckBox(panel, -1, "Alpha", (35, 40), (150, 20))
- wx.CheckBox(panel, -1, "Beta", (35, 60), (150, 20))
- wx.CheckBox(panel, -1, "Gamma", (35, 80), (150, 20))
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- CheckBoxFrame().Show()
- app.MainLoop()
wx.CheckBox 有一个典型的wxPython 构造函数:
- wx.CheckBox(parent, id, label, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name="checkBox")
label 参数是复选框的标签文本。复选框没有样式标记,但是它们产生属于自己的独一无二的命令事件:EVT_CHECKBOX 。wx.CheckBox 的开关状态可以使用GetValue() 和SetValue(state) 方法来访问,并且其值是一个布尔值。IsChecked() 方法等同于GetValue() 方法,只是为了让代码看起来更易明白。
如何创建一组单选按钮(radio button )?
单选按钮是一种允许用户从几个选项中选择其一的窗口部件。与复选框不同,单选按钮是显式地成组配置,并且只能选择其中一个选项。当选择了新的选项时,上次的选择就关闭了。单选按钮的使用比复选框复杂些,因为它需要被组织到一组中以便使用。radio button 的名字得自于老式轿车上有着同样行为的成组的选择按钮。
在wxPython 中,有两种方法可以创建一组单选按钮。其一,wx.RadioButton ,它要求你一次创建一个按钮,而wx.RadioBox 使你可以使用单一对象来配置完整的一组按钮,这些按钮显示在一个矩形中。
wx.RadioButton 类更简单些,在单选按钮对其它窗口部件有直接影响或单选按钮不是布置在一个单一的矩形中的情况下,它是首选。图7.11显示了一组wx.RadioButton 对象的列子。
图7.11
我们在这个例子中使用wx.RadioButton 的原因是因为每个单选按钮控制着一个关联的文本控件。由于窗口部件是位于这组单选按钮之外的,所以我们不能只用一个单选按钮框。
如何创建单选按钮
例7.11显示了图7.11的代码,它管理单选按钮和文本控件之间的联系。
例7.11 使用wx.RadioButton 来控制另一个窗口部件
- import wx
- class RadioButtonFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Radio Example',
- size=(200, 200))
- panel = wx.Panel(self, -1)
- #创建单选按钮
- radio1 = wx.RadioButton(panel, -1, "Elmo", pos=(20, 50), style=wx.RB_GROUP)
- radio2 = wx.RadioButton(panel, -1, "Ernie", pos=(20, 80))
- radio3 = wx.RadioButton(panel, -1, "Bert", pos=(20, 110))
- #创建文本控件
- text1 = wx.TextCtrl(panel, -1, "", pos=(80, 50))
- text2 = wx.TextCtrl(panel, -1, "", pos=(80, 80))
- text3 = wx.TextCtrl(panel, -1, "", pos=(80, 110))
- self.texts = {"Elmo": text1, "Ernie": text2, "Bert": text3}#连接按钮和文本
- for eachText in [text2, text3]:
- eachText.Enable(False)
- for eachRadio in [radio1, radio2, radio3]:#绑定事件
- self.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, eachRadio)
- self.selectedText = text1
- def OnRadio(self, event):#事件处理器
- if self.selectedText:
- self.selectedText.Enable(False)
- radioSelected = event.GetEventObject()
- text = self.texts[radioSelected.GetLabel()]
- text.Enable(True)
- self.selectedText = text
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- RadioButtonFrame().Show()
- app.MainLoop()
我们创建了单选按钮和文本框,然后使用字典来建立它们间的连接。一个for 循环使得两个文本框无效,另一个for 循环绑定单选按钮命令事件。当事件发生的时候,当前活动的文本框变为无效,与被敲击的按钮相匹配的文本框变为有效。
wx.RadioButton 的使用类似于是wx.CheckBox 。它们的构造函数几乎是相同的,如下所示:
- wx.RadioButton(parent, id, label, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, name="radioButton")
在复选框中,label 是相应按钮的显示标签。
wx.RB_GROUP 样式声明该按钮位于一组单选按钮开头。一组单选按钮的定义是很重要的,因为它控制开关行为。当组中的一个按钮被选中时,先前被选中的按钮被切换到未选中状态。在一个单选按钮使用wx.RB_GROUP 被创建后,所有后来的被添加到相同父窗口部件中的单选按钮都被添加到同一组,直到另一单选按钮使用wx.RB_GROUP 被创建,并开始下一个组。在例7.11中,第一个单选按钮是使用wx.RB_GROUP 声明的,而后来的没有。结果导致所有的按钮都被认为在同一组中,这样一来,敲击它们中的一个时,先前被选中按钮将关闭。
使用单选框
通常,如果你想去显示一组按钮,分别声明它们不是最好的方法。取而代之,wxPython 使用wx.RadioBox 类让你能够创建一个单一的对象,该对象包含了完整的组。如图7.12所示,它看起来非常类似一组单选按钮。
图7.12
要使用wx.RadioBox 类,你所需要的全部就是构造函数。例7.12显示了图7.12的代码。
例7.12 建造单选框
- import wx
- class RadioBoxFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Radio Box Example',
- size=(350, 200))
- panel = wx.Panel(self, -1)
- sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
- 'six', 'seven', 'eight']
- wx.RadioBox(panel, -1, "A Radio Box", (10, 10), wx.DefaultSize,
- sampleList, 2, wx.RA_SPECIFY_COLS)
- wx.RadioBox(panel, -1, "", (150, 10), wx.DefaultSize,
- sampleList, 3, wx.RA_SPECIFY_COLS | wx.NO_BORDER)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- RadioBoxFrame().Show()
- app.MainLoop()
wx.RadioBox 的构造函数比简单的单选按钮更复杂,因为你需要去一下子为所有的按钮指定数据,如下所示:
- wx.RadioBox(parent, id, label, pos=wx.DefaultPosition,
- size=wxDefaultSize, choices=None, majorDimension=0,
- style=wx.RA_SPECIFY_COLS, validator=wx.DefaultValidator,
- name="radioBox")
label 参数是静态文本,它显示在单选框的边框上。这些按钮使用choices 参数指定,它是一个Python 的字符串标签的序列。
如同网格的sizer 一样,你通过使用规定一个维数的尺寸来指定wx.RadioBox 的尺度,wxPython 在另一维度上自动填充。维度的主尺寸使用majorDimension 参数指定。哪一维是主要的由样式标记决定。默认值是wx.RA_SPECIFY_COLS 。在本例中,左框的列数被设置为2,右框的列数被设置为3,行数由choices 列表中的元素数量动态的决定。如果你想得到相反的行为,你要将样式设置为wx.RA_SPECIFY_ROWS 。如果你想在单选框被敲击时响应命令事件,那么这个命令事件是EVT_RADIOBOX 。
wx.RadioBox 类有许多方法来管理框中的不同的单选按钮。这些方法使你能够处理一个特定的内部按钮,传递该按钮的索引。索引以0为开始,并按严格的顺序展开,它的顺序就是按钮标签传递给构造函数的顺序。表7.11列出了这些方法。
表7.11 wx.RadioBox 的方法
EnableItem(n , flag) :flag 参数是一个布尔值,它用于使索引为n的按钮有效或无效。要使整个框立即有效,使用Enable() 。
FindString(string) :根据给定的标签返回相关按钮的整数索引值,如果标签没有发现则返回-1。
GetCount() :返回框中按钮的数量。
GetItemLabel(n) SetItemLabel(n , string) :返回或设置索引为n的按钮的字符串标签。
GetSelection() GetStringSelection() SetSelection(n) SetStringSelection( string) :GetSelection() 和SetSelection() 方法处理当前所选择的单选按钮的整数索引。GetStringSelection() 返回当前所选择的按钮的字符串标签,SetStringSelection() 改变所选择的按钮的字符串标签为给定值。没有set *()产生EVT_RADIOBOX 事件。
ShowItem(item , show) :show 参数是一个布尔值,用于显示或隐藏索引为item 的按钮。
单选按钮不是给用户一系列选择的唯一方法。列表框和组合框占用的空间也少,也可以被配置来让用户从同一组中作多个选择。
如何创建一个列表框?
列 表框是提供给用户选择的另一机制。选项被放置在一个矩形的窗口中,用户可以选择一个或多个。列表框比单选按钮占据较少的空间,当选项的数目相对少的时候, 列表框是一个好的选择。然而,如果用户必须将滚动条拉很远才能看到所有的选项的话,那么它的效用就有所下降了。图7.13显示了一个wxPython 列表框。
在wxPython 中,列表框是类wx.ListBox 的元素。该类的方法使你能够处理列表中的选择。
如何创建一个列表框
例7.13显示了产生图7.13的代码
例7.13 使用wx.ListBox
- import wx
- class ListBoxFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'List Box Example',
- size=(250, 200))
- panel = wx.Panel(self, -1)
- sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
- 'six', 'seven', 'eight', 'nine', 'ten', 'eleven',
- 'twelve', 'thirteen', 'fourteen']
- listBox = wx.ListBox(panel, -1, (20, 20), (80, 120), sampleList,
- wx.LB_SINGLE)
- listBox.SetSelection(3)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- ListBoxFrame().Show()
- app.MainLoop()
wx.ListBox 的构造函数类似于单选框的,如下所示:
- wx.ListBox(parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, choices=None, style=0, validator=wx.DefaultValidator, name="listBox")
单选框和列表框的主要区别是wx.ListBox 没有label 属性。显示在列表中的元素放置在参数choices 中,它是一个字符串的序列。列表框有三种互斥的样式,它决定用户如何从列表框中选择元素,说明在表7.12中。
用户通常对于多选有一些问题,因为它们一般希望见到的是单选列表,对于多选来说可能是有挑战性的(就像单选题和多选题一样),尤其是对于那些易受困扰的用户。如果你使用了一个多选的列表,我们建议你清楚地标明该列表。
表7.12 列表框的选择类型样式
wx.LB_EXTENDED :用户可以通过使用shift 并敲击鼠标来选择一定范围内的连续的选项,或使用等同功能的按键。
wx.LB_MULTIPLE :用户可以一次选择多个选项(选项可以是不连续的)。实际上,在这种情况下,列表框的行为就像是一组复选框。
wx.LB_SINGLE :用户一次只能选一个选项。实际上,在这种情况下,列表框的行为就像是一组单选按钮。
有三种控制wx.ListBox 中滚动条的显示的样式,如表7.13所示。
表7.13 列表框的滚动条类型样式
wx.LB_ALWAYS_SB :列表框将始终显示一个垂直的滚动条,不管有没有必要。
wx.LB_HSCROLL :如果本地控支持,那么列表框在选择项太多时,将创建一个水平滚动条。
wx.LB_HSCROLL :列表框只在需要的时候显示一个垂直的滚动条。这是默认样式。
还有一个样式wx.LB_SORT ,它使得列表中的元素按字母顺序排序。
有两个专用于wx.ListBox 的命令事件。EVT_LISTBOX 事件在当列表中的一个元素被选择时触发(即使它是当前所选择的元素)。如果列表被双击,EVT_LISTBOX_DCLICK 事件发生。
有一些专用于列表框的方法,你可以用来处理框中的项目。表7.14对许多的方法作了说明。列表框中的项目索引从0开始。
一旦你有了一个列表框,自然就想把它与其它的窗口部件结合起来使用,如下拉菜单,或复选框。在下一节,我们对此作讨论。
表7.14 列表框的方法
Append(item) :把字符串项目添加到列表框的尾部。
Clear() :清空列表框。
Delete(n) :删除列表框中索引为n的项目。
Deselect(n) :在多重选择列表框中,导致位于位置n的选项取消选中。在其它样式中不起作用。
FindString(string) :返回给定字符串的整数位置,如果没有发现则返回-1。
GetCount() :返回列表中字符串的数量。
GetSelection() SetSelection(n , select) GetStringSelection() SetStringSelection(string , select)GetSelections() :GetSelection() 得到当前选择项的整数索引(仅对于单选列表)。对于多选列表,使用GetSelections() 来返回包含所选项目的整数位置的元组。对于单选列表,GetStringSelection() 返回当前选择的字符串。相应的set 方法使用布尔值参数select 设置指定字符串或索引选项的状态。使用这种方法改变选择不触发EVT_LISTBOX 事件。
GetString(n) SetString(n , string) :得到或设置位置n处的字符串。
InsertItems(items , pos) :插入参数items 中的字符串列表到该列表框中pos 参数所指定的位置前。位置0表示把项目放在列表的开头。
Selected(n) :返回对应于索引为n的项目的选择状态的布尔值。
Set(choices) :重新使用 choices 的内容设置列表框。
如何合并复选框和列表框?
你可以使用类wx.CheckListBox 来将复选框与列表框合并。图7.14显示了列表框和复选框在合并在一起的例子。
图7.14
wx.CheckListBox 的构造函数和大多数方法与wx.ListBox 的相同。它有一个新的事件:wx.EVT_CHECKLISTBOX ,它在当列表中的一个复选框被敲击时触发。它有两个管理复选框的新的方法:Check(n , check) 设置索引为n的项目的选择状态,IsChecked(item) 在给定的索引的项目是选中状态时返回True 。
如果我想要下拉形式的选择该怎么做?
下拉式选择是一种仅当下拉箭头被敲击时才显示选项的选择机制。它是显示所选元素的最简洁的方法,当屏幕空间很有限的时候,它是最有用的。图7.15显示了一个关闭的下拉式选择。图7.16显示了一个打开的下拉式选择。
图7.15
图7.16
下拉式选择的使用与标准的列表框是很相似的。例7.14显示了如何创建一个下拉式选择。
例7.14
- import wx
- class ChoiceFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Choice Example',
- size=(250, 200))
- panel = wx.Panel(self, -1)
- sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
- 'six', 'seven', 'eight']
- wx.StaticText(panel, -1, "Select one:", (15, 20))
- wx.Choice(panel, -1, (85, 18), choices=sampleList)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- ChoiceFrame().Show()
- app.MainLoop()
wx.Choice 的构造函数与列表框的基本相同:
- wx.Choice(parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, choices=None, style=0, validator=wx.DefaultValidator, name="choice")
wx.Choice 没有专门的样式,但是它有独特的命令事件:EVT_CHOICE 。几乎表7.14中所有适用于单选列表框的方法都适用于wx.Choice 对象。
我能够将文本域与列表合并在一起吗?
将文本域与列表合并在一起的窗口部件称为组合框,其本质上是一个下拉选择和文本框的组合。图7.17显示了一个组合框。
图7.17 左边是wx.CB_DropDOWN 样式,右边是wx.CB_SIMPLE 样式
在Windows 上,你可以使用右边的样式,它是一个列表框和文本框的组合。
创建组合框的代码与我们已经见过的选择是类似的。该类是wx.ComboBox ,它是wx.Choice 的一个子类。例7.15显示了图7.17的代码:
例7.15
- import wx
- class ComboBoxFrame(wx.Frame):
- def __init__(self):
- wx.Frame.__init__(self, None, -1, 'Combo Box Example',
- size=(350, 300))
- panel = wx.Panel(self, -1)
- sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
- 'six', 'seven', 'eight']
- wx.StaticText(panel, -1, "Select one:", (15, 15))
- wx.ComboBox(panel, -1, "default value", (15, 30), wx.DefaultSize,
- sampleList, wx.CB_DropDOWN)
- wx.ComboBox(panel, -1, "default value", (150, 30), wx.DefaultSize,
- sampleList, wx.CB_SIMPLE)
- if __name__ == '__main__':
- app = wx.PySimpleApp()
- ComboBoxFrame().Show()
- app.MainLoop()
wx.ComboBox 的构造函数如下所示:
- wx.ComboBox(parent, id, value="", pos=wx.DefaultPosition,
- size=wx.DefaultSize, choices, style=0,
- validator=wx.DefaultValidator, name="comboBox")
对于wx.ComboBox 来说有4种样式。其中的两种决定了如何绘制组合框:wx.CB_DropDOWN 创建一个带有下拉列表的组合框,wx.CB_SIMPLE 创建一个带有列表框的组合框。在Windows 上你可以只使用wx.CB_SIMPLE 样式。任何组合框都可以被指定为wx.CB_READONLY 样式,它防止用户在文本域中键入。当组合框被指定为只读时,所做的选择必须来自于选择列表的元素之一,即使你用程序来设置它也不行。最后wx.CB_SORT 样式导致选择列表中的元素按字母顺序显示。
由于wx.ComboBox 是wx.Choice 的子类,所有的wx.Choice 的方法都能被组合框调用,如表7.14所示。另外,还有许多方法被定义来处理文本组件,它们的行为同wx.TextCtrl (参见表7.4),所定义的方法有Copy() , Cut() ,GetInsertionPoint() , GetValue() , Paste() , Replace(from ,to , text) , Remove(from , to) ,SetInsertionPoint(pos) , SetInsertionPointEnd() ,和 SetValue() 。
from:http://wiki.woodpecker.org.cn/moin/WxPythonInAction/ChapterSeven
评论
我按照您的代码,写的一模一样,但是调试出的结果老是出错,我不知道为什么
代码:
import wx
class bucky(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Frame aka window',size=(300,200))
panel=wx.Panel(self)
pic=wx.Image("im.bmp",wx.BITMAP_TYPT_BMP).ConvertToBitmap()
self.button=wx.BitmapButton(panel,-1,pic,pos=(10,10))
self.Bind(wx.EVT_BUTTON,self.doMe,self.button)
self.button.SetDefault()
def doMe(self,event):
self.Destroy()
if __name__=='__main__':
app=wx.App(False)
frame=bucky(parent=None,id=-1)
frame.Show()
app.MainLoop()
出错内容:
Traceback (most recent call last):
File "D:/python/lizi", line 18, in <module>
frame=bucky(parent=None,id=-1)
File "D:/python/lizi", line 7, in __init__
pic=wx.Image("im.bmp",wx.BITMAP_TYPT_BMP).ConvertToBitmap()
AttributeError: 'module' object has no attribute 'BITMAP_TYPT_BMP'