wxPython 教程 (七): 部件

总目录:wxPython 教程目录   
本节内容:wxPython widgets 部件
本节译自:zetcode
上一篇:wxpython 教程 (六): 对话框
下一篇:wxPython 教程 (八): wxPython 高级 widgets

在本节中,我们将介绍基本的 wxPython widgets。每一个 widget 将会有一个小例子介绍。Widgets 是 应用的基本单元,wxPython 有很多基本 widgets:按钮、选择框、滑动器、列表框等。

本节将介绍以下  wxPython widgets,点击列表项可跳转至相关介绍:

wx.Button

wx.Button 是一个简单的 widget,仅包含一个文本字符串,用来触发某个动作。


#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        pnl = wx.Panel(self)
        cbtn = wx.Button(pnl, label='Close', pos=(20, 30))

        cbtn.Bind(wx.EVT_BUTTON, self.OnClose)

        self.SetSize((250, 200))
        self.SetTitle('wx.Button')
        self.Centre()
        self.Show(True)          
        
    def OnClose(self, e):
        
        self.Close(True)                  
        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main() 

在样例中,我们创建了一个 Close 按键,点击 Close 即可关闭应用。


cbtn = wx.Button(pnl, label='Close', pos=(20, 30))

在按钮的构造函数中,我们提供了按钮的文本标签以及它在 panel 上的位置。


cbtn.Bind(wx.EVT_BUTTON, self.OnClose)

当点击按钮时 wx.EVT_BUTTON 事件会被触发,我们定义了 OnClose() 方法来处理该事件。


def OnClose(self, e):
    
    self.Close(True)   

在 OnClose() 函数中,我们调用了 Close() 函数来关闭应用。

tutorial wxpython-jiaocheng

图:wx.Button

wx.ToggleButton

wx.ToggleButton 也是一种按钮,但它有两个状态:点击和非点击状态。通过点击按键可以在两种状态中切换。在特定场景中,这一功能将非常适用。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        pnl = wx.Panel(self)
        
        self.col = wx.Colour(0, 0, 0)

        rtb = wx.ToggleButton(pnl, label='red', pos=(20, 25))
        gtb = wx.ToggleButton(pnl, label='green', pos=(20, 60))
        btb = wx.ToggleButton(pnl, label='blue', pos=(20, 100))

        self.cpnl  = wx.Panel(pnl, pos=(150, 20), size=(110, 110))
        self.cpnl.SetBackgroundColour(self.col)

        rtb.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleRed)
        gtb.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleGreen)
        btb.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleBlue)

        self.SetSize((300, 200))
        self.SetTitle('Toggle buttons')
        self.Centre()
        self.Show(True)     

    def ToggleRed(self, e):
        
        obj = e.GetEventObject()
        isPressed = obj.GetValue()
        
        green = self.col.Green()
        blue = self.col.Blue()
        
        if isPressed:
            self.col.Set(255, green, blue)
        else:
            self.col.Set(0, green, blue)
            
        self.cpnl.SetBackgroundColour(self.col)
        self.cpnl.Refresh()

    def ToggleGreen(self, e):
        
        obj = e.GetEventObject()
        isPressed = obj.GetValue()
        
        red = self.col.Red()
        blue = self.col.Blue()        
        
        if isPressed:
            self.col.Set(red, 255, blue)
        else:
            self.col.Set(red, 0, blue)
            
        self.cpnl.SetBackgroundColour(self.col)
        self.cpnl.Refresh()

    def ToggleBlue(self, e):
        
        obj = e.GetEventObject()
        isPressed = obj.GetValue()
        
        red = self.col.Red()
        green = self.col.Green()        
        
        if isPressed:
            self.col.Set(red, green, 255)
        else:
            self.col.Set(red, green, 0)
            
        self.cpnl.SetBackgroundColour(self.col)     
        self.cpnl.Refresh()  
                                   
        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()    

我们创建了红色、绿色和蓝色的 Toggle button 和一个 Panel。点击 toggle button的时候,可以改变 panel 的颜色。

rtb = wx.ToggleButton(pnl, label='red', pos=(20, 25)) 

上面的代码创建了一个 wx.ToggleButton 部件。

self.cpnl  = wx.Panel(pnl, pos=(150, 20), size=(110, 110))
self.cpnl.SetBackgroundColour(self.col) 

新建了一个 Panel,颜色设置为 self.col。


rtb.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleRed) 

当我们点击 rtb 这个触发 button 的时候 ToggleRed() 会被调用。

def ToggleRed(self, e):
    
    obj = e.GetEventObject()
    isPressed = obj.GetValue()
    
    green = self.col.Green()
    blue = self.col.Blue()
    
    if isPressed:
        self.col.Set(255, green, blue)
    else:
        self.col.Set(0, green, blue)
        
    self.cpnl.SetBackgroundColour(self.col)

在 ToogleRed() 函数里,我们对 rtb 按钮是否被按下做出反应,来改变特定 panel 的颜色。

tutorial wxpython-jiaocheng

图:触发按钮

wx.StaticLine

这个 widget 在窗口上展示一个简单的直线,可以是竖直或水平的。


#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        pnl = wx.Panel(self)

        font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)
        heading = wx.StaticText(self, label='The Central Europe', pos=(130, 15))
        heading.SetFont(font)

        wx.StaticLine(self, pos=(25, 50), size=(300,1))

        wx.StaticText(self, label='Slovakia', pos=(25, 80))
        wx.StaticText(self, label='Hungary', pos=(25, 100))
        wx.StaticText(self, label='Poland', pos=(25, 120))
        wx.StaticText(self, label='Czech Republic', pos=(25, 140))
        wx.StaticText(self, label='Germany', pos=(25, 160))
        wx.StaticText(self, label='Slovenia', pos=(25, 180))
        wx.StaticText(self, label='Austria', pos=(25, 200))
        wx.StaticText(self, label='Switzerland', pos=(25, 220))

        wx.StaticText(self, label='5 445 000', pos=(250, 80))
        wx.StaticText(self, label='10 014 000', pos=(250, 100))
        wx.StaticText(self, label='38 186 000', pos=(250, 120))
        wx.StaticText(self, label='10 562 000', pos=(250, 140))
        wx.StaticText(self, label='81 799 000', pos=(250, 160))
        wx.StaticText(self, label='2 050 000', pos=(250, 180))
        wx.StaticText(self, label='8 414 000', pos=(250, 200))
        wx.StaticText(self, label='7 866 000', pos=(250, 220))

        wx.StaticLine(self, pos=(25, 260), size=(300,1))

        tsum = wx.StaticText(self, label='164 336 000', pos=(240, 280))
        sum_font = tsum.GetFont()
        sum_font.SetWeight(wx.BOLD)
        tsum.SetFont(sum_font)

        btn = wx.Button(self, label='Close', pos=(140, 310))

        btn.Bind(wx.EVT_BUTTON, self.OnClose)        
        
        self.SetSize((360, 380))
        self.SetTitle('wx.StaticLine')
        self.Centre()
        self.Show(True)      
        
    def OnClose(self, e):
        
        self.Close(True)    
                      
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    

if __name__ == '__main__':
    main()   

上面的脚本展示了中欧的国家和他们的人口, wx.StaticLine 让界面更加美观。


wx.StaticLine(self, pos=(25, 50), size=(300,1))

上面是 wx.StaticLine 的构造函数。

tutorial wxpython-jiaocheng

图:wx.StaticLine

wx.StaticText

wx.StaticText 展示一行或多行的只读文本。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        txt1 = '''I'm giving up the ghost of love
in the shadows cast on devotion
She is the one that I adore
creed of my silent suffocation
Break this bittersweet spell on me
lost in the arms of destiny'''

        txt2 = '''There is something in the way
You're always somewhere else
Feelings have deserted me
To a point of no return
I don't believe in God
But I pray for you'''

        pnl = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        
        st1 = wx.StaticText(pnl, label=txt1, style=wx.ALIGN_CENTRE)
        st2 = wx.StaticText(pnl, label=txt2, style=wx.ALIGN_CENTRE)
        
        vbox.Add(st1, flag=wx.ALL, border=5)
        vbox.Add(st2, flag=wx.ALL, border=5)
        pnl.SetSizer(vbox)
        
        self.SetSize((250, 260))
        self.SetTitle('Bittersweet')
        self.Centre()
        self.Show(True)          
                        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    

if __name__ == '__main__':
    main()   

在上面的例子中,我们展示了一首 Bittersweet 歌曲的两节歌词。

        txt1 = '''I'm giving up the ghost of love
in the shadows cast on devotion
She is the one that I adore
creed of my silent suffocation
Break this bittersweet spell on me
lost in the arms of destiny'''

上面是要在 wx.StaticText 展示的字符串。

st1 = wx.StaticText(pnl, label=txt1, style=wx.ALIGN_CENTRE)

我们创建了 wx.StaticText 部件,文字被居中展示。

tutorial wxpython-jiaocheng

图:wx.StaticText

wx.StaticBox

这是一个装饰部件,被用来逻辑上将一组部件包括起来。需要注意的是,该部件必须在它所包含的部件创建之前创建,且那些被包含的部件是 wx.StaticBox 的兄弟部件而非子部件。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        pnl = wx.Panel(self)
        
        wx.StaticBox(pnl, label='Personal Info', pos=(5, 5), size=(240, 170))
        wx.CheckBox(pnl, label='Male', pos=(15, 30))
        wx.CheckBox(pnl, label='Married', pos=(15, 55))
        wx.StaticText(pnl, label='Age', pos=(15, 95))
        wx.SpinCtrl(pnl, value='1', pos=(55, 90), size=(60, -1), min=1, max=120)
        
        btn = wx.Button(pnl, label='Ok', pos=(90, 185), size=(60, -1))

        btn.Bind(wx.EVT_BUTTON, self.OnClose)

        self.SetSize((270, 250))
        self.SetTitle('Static box')
        self.Centre()
        self.Show(True)          
        
    def OnClose(self, e):
        
        self.Close(True)    
               
        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  

上面的例子中,我们创建了一个 wx.StaticBox,它装饰了其他的 4 个部件。

tutorial wxpython-jiaocheng

图:Static box

wx.ComboBox

wx.ComboBox 是由一行文本域、一个带有下拉箭头图标的按钮和一个列表框所构成的部件。当你按下按钮时,将出现一个列表框,用户只可选择其中的一个选项。


#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        pnl = wx.Panel(self)
        
        distros = ['Ubuntu', 'Arch', 'Fedora', 'Debian', 'Mint']
        cb = wx.ComboBox(pnl, pos=(50, 30), choices=distros, 
            style=wx.CB_READONLY)

        self.st = wx.StaticText(pnl, label='', pos=(50, 140))
        cb.Bind(wx.EVT_COMBOBOX, self.OnSelect)
        
        self.SetSize((250, 230))
        self.SetTitle('wx.ComboBox')
        self.Centre()
        self.Show(True)          
        
    def OnSelect(self, e):
        
        i = e.GetString()
        self.st.SetLabel(i)
        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    

if __name__ == '__main__':
    main()   

被选择的选项将会显示在文本标签上。

distros = ['Ubuntu', 'Arch', 'Fedora', 'Debian', 'Mint']

单选框将包含以上列表的字符串。

cb = wx.ComboBox(pnl, pos=(50, 30), choices=distros, 
            style=wx.CB_READONLY)

上面代表新建了 wx.ComboBox,通过 choices 参数传入一个字符串列表, wx.CB_READONLY 使得列表的字符串只读,即不可编辑。

cb.Bind(wx.EVT_COMBOBOX, self.OnSelect)

当从单选框选择一个选项时, wx.EVT_COMBOBOX 事件将被触发。我们绑定了 OnSelect() 来处理该事件。

def OnSelect(self, e):
    
    i = e.GetString()
    self.st.SetLabel(i)

从单选框选择一个条目并设置标签文本。

tutorial wxpython-jiaocheng

图:wx.ComboBox

wx.CheckBox

wx.CheckBox 只有两个状态:打开或关闭。它有一个框和文本标签组成,文本标签可以设置为放在框的左边或者右边。当 wx.CheckBox 被选择之后,框里将出现一个对号√。

在上面的例子中,我们通过一个 wx.CheckBox 部件来决定是否显示或隐藏窗口的标题。


cb = wx.CheckBox(pnl, label='Show title', pos=(20, 20))

上面是 wx.CheckBox 部件的构造函数。


cb.SetValue(True)

由于窗口的标题应该是被默认显示的,所以我们通过 SetValue() 方法默认选择 wx.CheckBox。


cb.Bind(wx.EVT_CHECKBOX, self.ShowOrHideTitle)

当点击 wx.CheckBox 部件时,wx.EVT_CHECKBOX 事件将被触发,我们将其绑定至事件处理器 ShowOrHideTitle() 函数。

def ShowOrHideTitle(self, e):
    
    sender = e.GetEventObject()
    isChecked = sender.GetValue()
    
    if isChecked:
        self.SetTitle('wx.CheckBox')            
    else: 
        self.SetTitle('') 

在 ShowOrHideTitle() 方法中,我们通过 wx.CheckBox 的状态来决定是否隐藏或显示窗口的标题。

tutorial wxpython-jiaocheng

图:wx.CheckBox

wx.StatusBar

wx.StatusBar 用来展示应用的状态信息,可以被分成不同的部分来展示不同的信息。我们也可以把其他 widgets 插入到 wx.StatusBar 中。它可以作为 dialog 的替代选择,因为现在 dialog 被滥用,很多用户都不喜欢。我们可以通过两种方式新建 wx.StatusBar。可以直接创建 wx.StatusBar 然后调用 SetStatusBar() 函数,也可以简单的调用 CreateStatusBar() 函数即可,第二种方法创建了一个默认的 wx.StatusBar。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        pnl = wx.Panel(self)

        button = wx.Button(pnl, label='Button', pos=(20, 20))
        text = wx.CheckBox(pnl, label='CheckBox', pos=(20, 90))
        combo = wx.ComboBox(pnl, pos=(120, 22), choices=['Python', 'Ruby'])
        slider = wx.Slider(pnl, 5, 6, 1, 10, (120, 90), (110, -1))        

        pnl.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
        button.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
        text.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
        combo.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)
        slider.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)

        self.sb = self.CreateStatusBar()

        self.SetSize((250, 230))
        self.SetTitle('wx.Statusbar')
        self.Centre()
        self.Show(True)     

    def OnWidgetEnter(self, e):
        
        name = e.GetEventObject().GetClassName()
        self.sb.SetStatusText(name + ' widget')
        e.Skip()               
        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    

if __name__ == '__main__':
    main()   

在上面的例子中,我们新建了 wx.Frame 和 5 个其他的 widgets。如果我们把鼠标悬停在 widget 上面,它的名字将会被显示在 wx.StatusBar 上。


pnl.Bind(wx.EVT_ENTER_WINDOW, self.OnWidgetEnter)

当我们的鼠标进入到 widget 的区域时, EVT_ENTER_WINDOW 事件将被触发。

def OnWidgetEnter(self, e):
    
    name = e.GetEventObject().GetClassName()
    self.sb.SetStatusText(name + ' widget')
    e.Skip()

在 OnWidgetEnter() 函数中,我们得到鼠标进入的 widget 的名字,然后使用 SetStatusText() 方法设置了状态栏的文字。

tutorial wxpython-jiaocheng

图:wx.StatusBar

wx.RadioButton

wx.RadioButton 允许用户从一组选项中排他的选择一个唯一选项。通过对第一个 radio 按钮设置 wx.RB_GROUP 样式标记,可以将紧随其后的其他 radio 按钮囊括为一组。随后的 radio 按钮如果也被设置了 wx.RB_GROUP 样式标记,那表明将开始新的一组选择框。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   
            
        pnl = wx.Panel(self)

        self.rb1 = wx.RadioButton(pnl, label='Value A', pos=(10, 10), 
            style=wx.RB_GROUP)
        self.rb2 = wx.RadioButton(pnl, label='Value B', pos=(10, 30))
        self.rb3 = wx.RadioButton(pnl, label='Value C', pos=(10, 50))
        
        self.rb1.Bind(wx.EVT_RADIOBUTTON, self.SetVal)
        self.rb2.Bind(wx.EVT_RADIOBUTTON, self.SetVal)
        self.rb3.Bind(wx.EVT_RADIOBUTTON, self.SetVal)

        self.sb = self.CreateStatusBar(3)
        
        self.sb.SetStatusText("True", 0)
        self.sb.SetStatusText("False", 1)
        self.sb.SetStatusText("False", 2)   

        self.SetSize((210, 210))
        self.SetTitle('wx.RadioButton')
        self.Centre()
        self.Show(True)     

    def SetVal(self, e):
        
        state1 = str(self.rb1.GetValue())
        state2 = str(self.rb2.GetValue())
        state3 = str(self.rb3.GetValue())

        self.sb.SetStatusText(state1, 0)
        self.sb.SetStatusText(state2, 1)
        self.sb.SetStatusText(state3, 2)            
        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    

if __name__ == '__main__':
    main()   

我们创建了一组 3 个 radio 按钮,每个按钮的状态被显示在 statusBar 上。

self.rb1 = wx.RadioButton(pnl, label='Value A', pos=(10, 10), 
    style=wx.RB_GROUP)
self.rb2 = wx.RadioButton(pnl, label='Value B', pos=(10, 30))
self.rb3 = wx.RadioButton(pnl, label='Value C', pos=(10, 50))

上面的代码新建了 3 个 radio 按钮,其中第一个被设置了 wx.RB_GROUP 样式,表明接下来的 radio 都将是同一组。

self.rb1.Bind(wx.EVT_RADIOBUTTON, self.SetVal)

我们将 wx.EVT_RADIOBUTTON 事件绑定至 SetVal() 时间处理函数上。


self.sb = self.CreateStatusBar(3)

self.sb.SetStatusText("True", 0)
self.sb.SetStatusText("False", 1)
self.sb.SetStatusText("False", 2) 

我们创建了分三部分的 statusbar,并根据对应 radio 的状态设置了初始文字。


def SetVal(self, e):
    
    state1 = str(self.rb1.GetValue())
    state2 = str(self.rb2.GetValue())
    state3 = str(self.rb3.GetValue())

    self.sb.SetStatusText(state1, 0)
    self.sb.SetStatusText(state2, 1)
    self.sb.SetStatusText(state3, 2)

在 SetVal() 函数中,我们对状态栏的文本进行了更新。

tutorial wxpython-jiaocheng

图:wx.RadioButton

wx.Gauge

wx.Gauge 主要用在时间较长的任务场景,用来显示当前任务的状态。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx

TASK_RANGE = 50

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   
        
        self.timer = wx.Timer(self, 1)
        self.count = 0

        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)

        pnl = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)

        self.gauge = wx.Gauge(pnl, range=TASK_RANGE, size=(250, 25))
        self.btn1 = wx.Button(pnl, wx.ID_OK)
        self.btn2 = wx.Button(pnl, wx.ID_STOP)
        self.text = wx.StaticText(pnl, label='Task to be done')

        self.Bind(wx.EVT_BUTTON, self.OnOk, self.btn1)
        self.Bind(wx.EVT_BUTTON, self.OnStop, self.btn2)

        hbox1.Add(self.gauge, proportion=1, flag=wx.ALIGN_CENTRE)
        hbox2.Add(self.btn1, proportion=1, flag=wx.RIGHT, border=10)
        hbox2.Add(self.btn2, proportion=1)
        hbox3.Add(self.text, proportion=1)
        vbox.Add((0, 30))
        vbox.Add(hbox1, flag=wx.ALIGN_CENTRE)
        vbox.Add((0, 20))
        vbox.Add(hbox2, proportion=1, flag=wx.ALIGN_CENTRE)
        vbox.Add(hbox3, proportion=1, flag=wx.ALIGN_CENTRE)

        pnl.SetSizer(vbox)
        
        self.SetSize((300, 200))
        self.SetTitle('wx.Gauge')
        self.Centre()
        self.Show(True)     

    def OnOk(self, e):
        
        if self.count >= TASK_RANGE:
            return

        self.timer.Start(100)
        self.text.SetLabel('Task in Progress')

    def OnStop(self, e):
        
        if self.count == 0 or self.count >= TASK_RANGE or not self.timer.IsRunning():
            return

        self.timer.Stop()
        self.text.SetLabel('Task Interrupted')
        
    def OnTimer(self, e):
        
        self.count = self.count + 1
        self.gauge.SetValue(self.count)
        
        if self.count == TASK_RANGE:

            self.timer.Stop()
            self.text.SetLabel('Task Completed')
                      
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    

if __name__ == '__main__':
    main()   

我们创建了一个 进度条(gauge)和两个按钮。一个按钮开始走进度条,一个按钮停止走进度条。

self.timer = wx.Timer(self, 1)
self.count = 0

我们使用了 wx.Timer 来在特定的时间区间来执行代码,我们将在定义好的时间来更新进度条。 count 变量用来决定目前任务已经完成的比例。


self.gauge = wx.Gauge(pnl, range=TASK_RANGE, size=(250, 25))

上面是 wx.Gauge 部件的构造函数, range 参数定义了该部件最大的整数区间。

def OnOk(self, e):
    
    if self.count >= TASK_RANGE:
        return

    self.timer.Start(100)
    self.text.SetLabel('Task in Progress')

当我们点击 OK 按钮时,OnOK() 方法将被调用。首先我们检查 count 变量是否还在任务的整数区间内。如果不在,我们直接返回。如果还在,表明任务还在继续,我们开始 timer 定时器并更新静态文本。

def OnStop(self, e):
    
    if self.count == 0 or self.count >= TASK_RANGE or not self.timer.IsRunning():
        return

    self.timer.Stop()
    self.text.SetLabel('Task Interrupted')

当我们点击 Stop 按钮时,OnStop() 函数将被调用。我们检查了各种条件,符合的话我们停止定时器并更新静态文本。

def OnTimer(self, e):
    
    self.count = self.count +  1
    self.gauge.SetValue(self.count)
    
    if self.count == TASK_RANGE:

        self.timer.Stop()
        self.text.SetLabel('Task Completed')

OnTimer() 方法在 timer 开始后被周期调用。在该方法内,我们更新 count 参数和进度条部件。如果 count 等于 TASK_RANGE,我们停止 timer 并更新静态文本。

tutorial wxpython-jiaocheng

图:wx.Gauge

wx.Slider

wx.Slider 部件有一个简单的操作柄,可以向前或向后滑动。我们可以使用它完成特定的任务。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        pnl = wx.Panel(self)

        sld = wx.Slider(pnl, value=200, minValue=150, maxValue=500, pos=(20, 20), 
            size=(250, -1), style=wx.SL_HORIZONTAL)
        
        sld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
        
        self.txt = wx.StaticText(pnl, label='200', pos=(20, 90))               
        
        self.SetSize((290, 200))
        self.SetTitle('wx.Slider')
        self.Centre()
        self.Show(True)    

    def OnSliderScroll(self, e):
        
        obj = e.GetEventObject()
        val = obj.GetValue()
        
        self.txt.SetLabel(str(val))        

                      
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    

if __name__ == '__main__':
    main()   

在 slider 中选择的值将被显示在下面的静态文本中。

sld = wx.Slider(pnl, value=200, minValue=150, maxValue=500, pos=(20, 20), 
            size=(250, -1), style=wx.SL_HORIZONTAL)

上面的代码创建了 wx.Slider。在构造函数中,我们提供了它的初始位置,以及最大、最小的滑动位置,还有设定了它的水平方向。

sld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)

当 wx.EVT_SCROLL 时间被触发的时候,将调用 OnSliderScroll() 函数。

self.txt = wx.StaticText(pnl, label='200', pos=(20, 90)) 

当前 slider 的值将被显示在下方的静态文本中。

def OnSliderScroll(self, e):
    
    obj = e.GetEventObject()
    val = obj.GetValue()
    
    self.txt.SetLabel(str(val)) 

在 OnSliderScroll() 方法中,我们得到了事件的发送者并得到其当前被选择的值,然后将其设置到静态文本中。

tutorial wxpython-jiaocheng

图:wx.Slider

wx.SpinCtrl

wx.SpinCtrl 可以让我们对一个值进行增加或减少,它有两个按钮,一个带向上箭头,一个带向下箭头。用户可以直接输入数值,也可以通过两个箭头来对数值进行上下增减。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx


class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
    def InitUI(self):   

        pnl = wx.Panel(self)

        
        wx.StaticText(self, label='Convert Fahrenheit temperature to Celsius', 
            pos=(20,20))
        wx.StaticText(self, label='Fahrenheit: ', pos=(20, 80))
        wx.StaticText(self, label='Celsius: ', pos=(20, 150))
        
        self.celsius = wx.StaticText(self, label='', pos=(150, 150))
        self.sc = wx.SpinCtrl(self, value='0', pos=(150, 75), size=(60, -1))
        self.sc.SetRange(-459, 1000)
        
        btn = wx.Button(self, label='Compute', pos=(70, 230))
        btn.SetFocus()
        cbtn = wx.Button(self, label='Close', pos=(185, 230))

        btn.Bind(wx.EVT_BUTTON, self.OnCompute)
        cbtn.Bind(wx.EVT_BUTTON, self.OnClose)
           
        self.SetSize((350, 310))
        self.SetTitle('wx.SpinCtrl')
        self.Centre()
        self.Show(True)          
        
    def OnClose(self, e):
        
        self.Close(True)    
        
    def OnCompute(self, e):
        
        fahr = self.sc.GetValue()
        cels = round((fahr - 32) * 5 / 9.0, 2)
        self.celsius.SetLabel(str(cels))        
                      
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    

if __name__ == '__main__':
    main()     

上面的脚本将华氏温度转变为摄氏度。我们使用 wx.SpinCtrl 部件供用户来选择华氏温度的值。

self.sc = wx.SpinCtrl(self, value='0', pos=(150, 75), size=(60, -1))
self.sc.SetRange(-459, 1000)

在上面代码中,我们创建了一个初始值为 0 的 wx.SpinCtrl 部件,并通过 SetRange() 方法设置了该部件的取值范围。

def OnCompute(self, e):
    
    fahr = self.sc.GetValue()
    cels = round((fahr - 32) * 5 / 9.0, 2)
    self.celsius.SetLabel(str(cels)) 

当我们点击 compute 按钮时,将会调用 OnCompute() 函数。在该函数中,我们获取用户设定的华氏温度值,并计算对应的摄氏温度值,将其更新在静态文本上。
tutorial wxpython-jiaocheng

图:wx.SpinCtrl

在本节中,我们主要讲解了各种核心 wxPython 部件。


上一篇:wxpython 教程 (六): 对话框              下一篇:wxPython 教程 (八): wxPython 高级 widgets

《wxPython 教程 (七): 部件》有2个想法

  1. 您好,我想实现一个功能,就是做一个GUI界面,界面上两个输入框和一个运行按钮。输入框可以输入文本,也可以输入数字。点击运行按钮,运行一个自定义函数,请问有什么好的教程推荐的呢

发表评论

电子邮件地址不会被公开。 必填项已用*标注