wxpython基本控件之按钮控件的用法

发布时间:2020-06-04编辑:脚本学堂
本文介绍了wxpython基本控件中按钮控件的用法,重点讨论文本按钮、位图按钮、开关按钮(toggle buttons )和通用(generic )按钮的用法。

使用按钮工作
 
在wxpython 中有很多不同类型的按钮。

专题教程:wxpython中文教程

重点讨论文本按钮、位图按钮、开关按钮(toggle buttons )和通用(generic )按钮。
 
如何生成一个按钮?
 
在第一部分(part 1)中,我们已经说明了几个按钮的例子,所以这里我们只简短的涉及它的一些基本的东西。
 
使用按钮是非常简单的。

例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 。
 
如何生成一个位图按钮?
 
有时候,你可能想在你的按钮上显示一个图片,而非一个文本标签。
 
在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 )看起来十分像文本按钮,但它的行为更像复选框,它的选择或非选择状态是可视化的。换句话说,当你按下一个开关按钮(toggle button )时,它将一直保持被按下的状态直到你再次敲击它。
 
在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的代码。第二个导入语句: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 水平和垂直滑块的显示代码
 

复制代码 代码示例:
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 的微调控制器控件。
 
在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 显示并更新一个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 中,有多种窗口部件帮助用户处理这种任务,包括复选框、单选按钮、列表框和组合框。接下来的部分将介绍这些窗口部件。