構建一個最簡單的wxPython 程序至少需要一個wx.App 對象和一個wx.Frame 對象。
模板:
import wx # 加載模塊
# 繼承窗體類
class MyFrame(wx.Frame):
def __init__(self):
# 初始化父類
super().__init__(parent=None,title="第一個窗體程序!",size=(500,200))
self.Center() # 設置窗口居中
# 這裏可以添加自己的設計代碼
# ·······
# 這裏可以添加自己的設計代碼
# wx.App 對象代表當前應用程序
class App(wx.App):
def OnInit(self):
myFrame=MyFrame() # 創建窗體實例
myFrame.Show() # 顯示窗口
return True
def OnExit(self):
print(' 應用程序退出')
return 0
if __name__ =="__main__":
app=App() # 創建應用程序對象
app.MainLoop() # 進入主事件循環
一、wx.Frame類介紹:
wx.Frame(parent, id=-1, title= "", pos=wx.DefaultPosition, size=wx.DefaultSize,style=wx.DEFAULT_FRAME_STYLE,name="frame")
parent : 框架的父窗口。對於頂級窗口,這個值是None 。
id : 關於新窗口的wxPython ID 號。可以明確地傳遞一個 值。如果 傳遞-1 ,wxPython 自動生成一個新的ID 。
title : 窗口的標題。
pos : 一個wx.Point 對象,它指定這個新窗口的左上角在屏幕中的位置。
size : 一個wx.Size 對象,它指定這個窗口的初始尺寸。(-1,-1) 將讓系統決定窗口的初始尺寸。
style: 指定窗口的類型的常量。可以使用或運算來組合它們。
name : 框架的內在的名字。以後可以使用它來尋找這個窗口。
二、窗體佈局
wxPython 提供了8 個佈局管理器類,包括wx.Sizer 、wx.BoxSizer 、wx.StaticBoxSizer 、wx.WrapSizer 、wx.StdDialogButtonSizer 、wx.GridSizer 、wx.FlexGridSizer 、wx.GridBagSizer。
其中wx.Sizer 是佈局管理器的根類, 一般不會直接使用wx.Sizer ,而是使用它的子類 ,最常用的有:wx.BoxSizer 、wx.StaticBoxSizer 、wx.GridSizer 和wx.FlexGridSizer 。
1. Box 佈局
Box 佈局類是wx.BoxSizer ,Box 佈局是所有佈局中最常用的,它可以讓其中的子窗口(或控件)沿垂直或水平方向佈局,創建wx.BoxSizer 對象時可以指定佈局方向。
當需要添加子窗口(或控件)到父窗口時,需要調用wx.BoxSizer 對象Add() 方法,Add() 方法是從父類wx.Sizer 繼承而來的,Add() 方法的語法說明如下:
Add(window, proportion=0, flag=0, border=0, userData=None)
Add(sizer, proportion=0, flag=0, border=0,userData=None)
Add(size, proportion=0, flag=0, border=0, userData=None)
其中proportion 參數僅被wx.BoxSizer 使用,用來設置當前子窗口(或控件)在父窗口所佔空間比例 ,proportion=0 表示保持本身大小;flag 是參數標誌,用來控制對齊、邊框和調整尺寸;border 參數用來設置邊框的寬度;userData參數可被用來傳遞額外的數據。
flag標誌:
對齊
邊框
尺寸
2. StaticBox 佈局
StaticBox 佈局類是wx.StaticBoxSizer ,繼承於wx.BoxSizer 。StaticBox 佈局等同於Box ,只是在Box 周圍多了一個附加的帶靜態文本的邊框。
3. Grid 佈局
Grid 佈局類是wx.GridSizer ,Grid 佈局以網格形式對子窗口(或控件)進行擺放,容器被分成大小相等的矩形,一個矩形中放置一個子窗口(或控件)。
四種構造方法:
wx.GridSizer(rows, cols, vgap, hgap) :
創建指定行數和列數的wx.GridSizer 對象,並指定水平和垂直間隙,參數hgap 是水平間隙,參數vgap 是垂直間隙。添加的子窗口(或控件)個數超過rows 與cols之積,則引發異常。
wx.GridSizer(rows, cols, gap) :
同wx.GridSizer(rows, cols,vgap, hgap) ,gap 參數指定垂直間隙和水平間隙,gap 參數是wx.Size 類型,例如wx.Size(2, 3) 是設置水平間隙爲2 像素,垂直間隙爲3 像素。
wx.GridSizer(cols, vgap, hgap) :
創建指定列數的wx.GridSizer 對象,並指定水平和垂直間隙。由於沒有限定行數,所以添加的子窗口(或控件)個數沒有限制。
wx.GridSizer(cols, gap=wx.Size(0, 0)) :
wx.GridSizer(cols,vgap, hgap) ,gap 參數指定垂直間隙和水平間隙,gap 參數是wx.Size類型。
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="Grid佈局",size=(300,300))
self.Center()
panel=wx.Panel(self)
grid= wx.GridSizer(3,3,1,1)
for i in range(9):
item=wx.Button(parent=panel,id=-1,label=str(i+1))
grid.Add(item,1,flag=wx.EXPAND)
panel.SetSizer(grid) # 設置佈局
class App(wx.App):
def OnInit(self):
frame=MyFrame()
frame.Show()
return True
if __name__=="__main__":
app=App()
app.MainLoop()
4. FlexGrid 佈局
Grid 佈局時網格大小是固定的,如果想網格大小不同可以使用FlexGrid。
FlexGrid 佈局類是wx.FlexGridSizer ,它的父類是wx.GridSizer 。
wx.FlexGridSizer 的構造方法與wx.GridSizer 相同,這裏不再贅述。wx.FlexGridSizer 有兩個特殊方法如下:
1 )AddGrowableRow(idx, proportion=0) :
指定行是可擴展的,參數idx 是行索引,從零開始,參數proportion 設置該行所佔空間比例。
2 )AddGrowableCol(idx, proportion=0) :
指定列是可擴展的,參數idx 是列索引,從零開始,參數proportion 設置該列所佔空間比例。上述方法中的proportion 參數 默認是0 ,表示各個列佔用空間是均等的。
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="FlexGrid佈局",size=(400,200))
self.Center()
panel=wx.Panel(self)
flexgrid=wx.FlexGridSizer(3,2,10,10)
text1=wx.StaticText(parent=panel,id=-1,label="標題")
boxctrl1=wx.TextCtrl(parent=panel,id=1)
text2 = wx.StaticText(parent=panel, id=-1, label="作者")
boxctrl2 = wx.TextCtrl(parent=panel, id=2)
text3 = wx.StaticText(parent=panel, id=-1, label="內容")
boxctrl3 = wx.TextCtrl(parent=panel, id=3,style=wx.TE_MULTILINE)
flexgrid.Add(text1)
flexgrid.Add(boxctrl1,1,flag=wx.EXPAND)
flexgrid.Add(text2)
flexgrid.Add(boxctrl2,1,flag=wx.EXPAND)
flexgrid.Add(text3)
flexgrid.Add(boxctrl3,1,flag=wx.EXPAND)
flexgrid.AddGrowableCol(1,2)
flexgrid.AddGrowableRow(2, 3)
box=wx.BoxSizer()
box.Add(flexgrid,1,flag=wx.ALL|wx.EXPAND,border=10)
panel.SetSizer(box)
class App(wx.App):
def OnInit(self):
frame=MyFrame()
frame.Show()
return True
if __name__=="__main__":
app=App()
app.MainLoop()
三、wxPython控件
wxPython 的所有控件都繼承自wx.Control 類。主要有文本輸入控件、按鈕、靜態文本、列表、單選按鈕 、複選框等控件。
1. 靜態文本
wxPython 中靜態文本類是 wx.StaticText
,可以顯示文本。
構造函數:
wx.StataicText(parent, id, label, pos=wx.DefaultPosition,size=wx.DefaultSize, style=0, name="staticText")
2. 按鈕
wxPython 中的按鈕主要有wx.Button 、wx.BitmapButton和wx.ToggleButton 三個。wx.Button 是普通按鈕,wx.BitmapButton 是帶有圖標的按鈕,wx.ToggleButton 是能進行兩種狀態切換的按鈕。
構造函數:
wx.Button(parent, id, label, pos, size=wxDefaultSize,style=0, validator, name='button')
參數label 是顯示在按鈕上的文本。它可以在程序運行期間使用SetLabel() 來改變,並且使GetLabel() 來獲取。另外兩個有用的方法是GetDefaultSize() 和SetDefault() 。GetDefaultSize() 返回系統默認按鈕的尺寸(對於框架間的一致性是有用的);SetDefault() 設置按鈕爲對話框或框架的默認按鈕。默認按鈕的繪製不同於其它按鈕,它在對話框獲得焦點時,通常按下回車鍵被激活。
3. 文本輸入控件
文本 輸入控件類是wx.TextCtrl 。
4. 複選框
構造函數:
wx.CheckBox(parent, id, label,pos=wx.DefaultPosition, size=wx.DefaultSize,style=0, name='checkBox')
命令事件:EVT_CHECKBOX
wx.CheckBox 的開關狀態可以使用GetValue()和getValue(state) 方法來訪問,並且其值是一個布爾值。IsChecked() 方法等同於GetValue()方法。
5. 單選按鈕
構造函數:
wx.RadioButton(parent, id, label,pos=wx.DefaultPosition, size=wx.DefaultSize,style=0, validator=wx.DefaultValidator, name='radioButton')
創建wx.RadioButton 對象時設置style=wx.RB_GROUP ,這說明是一個組的開始,直到遇到另外設置style=wx.RB_GROUP 的wx.RadioButton對象爲止都是同一個組。
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="複選框與單選框",size=(500,200))
self.Center()
panel=wx.Panel(self)
hbox1=wx.BoxSizer()
text1=wx.StaticText(parent=panel,id=0,label="選擇你喜歡的編程語言:")
check1=wx.CheckBox(parent=panel,id=1,label="Python")
check2 = wx.CheckBox(parent=panel, id=2, label="Java")
check3 = wx.CheckBox(parent=panel, id=3, label="C++")
check2.SetValue(True)
hbox1.Add(text1,flag=wx.LEFT|wx.RIGHT,border=10)
hbox1.Add(check1, flag=wx.LEFT | wx.RIGHT, border=10)
hbox1.Add(check2, flag=wx.LEFT | wx.RIGHT, border=10)
hbox1.Add(check3, flag=wx.LEFT | wx.RIGHT, border=10)
self.Bind(wx.EVT_CHECKBOX,self.on_check,id=1,id2=3)
hbox2=wx.BoxSizer()
text2=wx.StaticText(parent=panel,id=4,label="選擇性別:")
radio1=wx.RadioButton(parent=panel,id=5,label="男",style=wx.RB_GROUP)
radio2 = wx.RadioButton(parent=panel, id=6, label="女")
hbox2.Add(text2,flag=wx.LEFT|wx.RIGHT,border=10)
hbox2.Add(radio1, flag=wx.LEFT | wx.RIGHT, border=10)
hbox2.Add(radio2, flag=wx.LEFT | wx.RIGHT, border=10)
self.Bind(wx.EVT_RADIOBUTTON, self.on_radio1, id=5, id2=6)
hbox3 = wx.BoxSizer()
text3 = wx.StaticText(parent=panel, id=10, label="選擇你喜歡吃的水果:")
radio3 = wx.RadioButton(parent=panel, id=7, label="蘋果",style=wx.RB_GROUP)
radio4 = wx.RadioButton(parent=panel, id=8, label="橘子")
radio5 = wx.RadioButton(parent=panel, id=9, label="香蕉")
hbox3.Add(text3, flag=wx.LEFT | wx.RIGHT, border=10)
hbox3.Add(radio3, flag=wx.LEFT | wx.RIGHT, border=10)
hbox3.Add(radio4, flag=wx.LEFT | wx.RIGHT, border=10)
hbox3.Add(radio5, flag=wx.LEFT | wx.RIGHT, border=10)
self.Bind(wx.EVT_RADIOBUTTON, self.on_radio2, id=7, id2=9)
vbox=wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox1,flag=wx.ALL|wx.EXPAND,border=10)
vbox.Add(hbox2, flag=wx.ALL | wx.EXPAND, border=10)
vbox.Add(hbox3, flag=wx.ALL | wx.EXPAND, border=10)
panel.SetSizer(vbox)
ico=wx.Icon("C:\\Users\\自由自在\\Desktop\\Python應用開發\\Python(1)\\素材\wxPython\\icon\\0.png",wx.BITMAP_TYPE_ANY)
self.SetIcon(ico)
self.CreateStatusBar()
self.SetStatusText("準備就緒")
def on_check(self,event):
ch=event.GetEventObject()
self.SetStatusText("選擇: "+ch.GetLabel()+" 狀態:"+str(event.IsChecked()))
def on_radio1(self,event):
ch=event.GetEventObject()
self.SetStatusText("第一組 "+ch.GetLabel()+" 被選中")
def on_radio2(self,event):
ch=event.GetEventObject()
self.SetStatusText("第二組 "+ch.GetLabel()+" 被選中")
class App(wx.App):
def OnInit(self):
myFrame=MyFrame()
myFrame.Show()
return True
if __name__ =="__main__":
app=App()
app.MainLoop()
6. 下拉列表
wxPython 提供了兩種下拉列表控件類wx.ComboBox 和wx.Choice 。wx.ComboBox 默認它的文本框是可以修改的,wx.Choice 是隻讀不可以修改的,除此之外它們沒有區別。
構造函數:
wx.ComboBox(parent, id, value="",pos=wx.DefaultPosition, size=wx.DefaultSize, choices,style=0, validator=wx.DefaultValidator,name="comboBox")
value 用來設置默認值,即下拉列表的文本框中初始顯示的內容;
choices 參數用來設置列表選擇項,它是列表類型;
style 參數用來設置wx.ComboBox 風格樣式,主要有4 種風格:
wx.CB_SIMPLE :列表部分一直顯示不收起來。wx.CB_DROPDOWN :默認風格,單擊向下按鈕列表部分展開,選擇完成收起來。wx.CB_READONLY :文本框不可修改。
wx.CB_SORT :對列表選擇項進行排序。
8wx.Choice 的構造方法與列表框的基本相同:*
wx.Choice(parent, id, pos=wx.DefaultPosition,size=wx.DefaultSize, choices=None, style=0,validator=wx.DefaultValidator, name="choice")
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="下拉列表",size=(400,200))
self.Center()
panel=wx.Panel(self)
text1=wx.StaticText(parent=panel,id=-1,label="選擇喜歡的編程語言:")
list1=["Python","Java","C++"]
combobox=wx.ComboBox(parent=panel,id=-1,value="C++",choices=list1,
style=wx.CB_SORT|wx.TE_PROCESS_ENTER)
self.Bind(wx.EVT_COMBOBOX,self.on_combobox,combobox)
hbox1=wx.BoxSizer()
hbox1.Add(text1,1,flag=wx.LEFT|wx.RIGHT|wx.FIXED_MINSIZE,border=5)
hbox1.Add(combobox, 1, flag=wx.FIXED_MINSIZE|wx.ALL)
list2=["男","女"]
text2 = wx.StaticText(parent=panel, id=-1, label="選擇性別:")
choice=wx.Choice(parent=panel,id=-1,choices=list2)
choice.SetSelection(0)
self.Bind(wx.EVT_CHOICE,self.on_choice,choice)
hbox2 = wx.BoxSizer()
hbox2.Add(text2, 1, flag=wx.LEFT|wx.RIGHT |wx.FIXED_MINSIZE,border=5)
hbox2.Add(choice, 1, flag=wx.ALL |wx.FIXED_MINSIZE)
vbox=wx.BoxSizer(wx.VERTICAL)
vbox.Add(hbox1,1,flag=wx.ALL |wx.EXPAND,border=5)
vbox.Add(hbox2, 1,flag=wx.ALL |wx.EXPAND,border=5)
panel.SetSizer(vbox)
self.CreateStatusBar()
self.SetStatusText("準備就緒")
def on_combobox(self,event):
str=event.GetString()
self.SetStatusText("選擇:"+str)
def on_choice(self,event):
str = event.GetString()
self.SetStatusText("選擇:" + str)
class App(wx.App):
def OnInit(self):
frame=MyFrame()
frame.Show()
return True
if __name__=="__main__":
app=App()
app.MainLoop()
7. 列表
列表控件類似於下拉列表控件,只是沒有文本框,只有一個列表選項。列表控件可以單選或多選。列表控件類是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 中,它是一個字符串的序列。列表框有三種互斥的樣式,它決定用戶如何從列表框中選擇元素。
(1 )wx.LB_EXTENDED :用戶可以通過使用shift 並敲擊鼠標來選擇一定範圍內的連續的 選項,或使用等同功能的按鍵。
(2 )wx.LB_MULTIPLE :用戶可以一次選擇多個選項(選項可以是不連續的)。實際上,在這種情況下,列表框的行爲就像是一組複選框。
(3 )wx.LB_SINGLE :用戶一次只能選一個選項。實際上,在這種情況下,列表框的行爲 就像是一組單選按鈕。
8. 靜態圖片控件
靜態圖片控件類是wx.StaticBitmap ,靜態圖片控件用來顯示一張圖片,圖片可以是wx.Python 所支持的任何圖片格式。
圖片替換後,需要重新繪製窗口,否則佈局會發生混亂。self.panel.Layout() 是重新設置panel 面板佈局,因爲靜態圖片控件是添加在panel面板上的。
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="靜態圖片控件",size=(300,300))
self.Center()
self.panel=wx.Panel(self)
button1=wx.Button(parent=self.panel,id=1,label="Button1")
button2= wx.Button(parent=self.panel, id=2, label="Button2")
self.Bind(wx.EVT_BUTTON,self.on_button,id=1,id2=2)
self.bmaps=[wx.Bitmap("C:\\Users\\自由自在\\Desktop\\Python應用開發\\Python(1)\\素材\wxPython\\images\\bird3.gif",wx.BITMAP_TYPE_ANY),
wx.Bitmap("C:\\Users\\自由自在\\Desktop\\Python應用開發\\Python(1)\\素材\wxPython\\images\\bird4.gif",wx.BITMAP_TYPE_ANY),
wx.Bitmap("C:\\Users\\自由自在\\Desktop\\Python應用開發\\Python(1)\\素材\wxPython\\images\\bird5.gif",wx.BITMAP_TYPE_ANY)]
self.image=wx.StaticBitmap(self.panel,-1,self.bmaps[0])
vbox=wx.BoxSizer(wx.VERTICAL)
vbox.Add(button1,1,flag=wx.CENTER|wx.EXPAND)
vbox.Add(button2, 1, flag=wx.CENTER | wx.EXPAND)
vbox.Add(self.image, 3, flag=wx.CENTER | wx.EXPAND)
self.panel.SetSizer(vbox)
def on_button(self,event):
id=event.GetId()
if id==1:
self.image.SetBitmap(self.bmaps[1])
else:
self.image.SetBitmap(self.bmaps[2])
self.panel.Layout()
class App(wx.App):
def OnInit(self):
frame=MyFrame()
frame.Show()
return True
if __name__=="__main__":
app=App()
app.MainLoop()
9. 使用網格
當有大量數據需要展示時,可以使用網格。
wxPython 的網格類似於Excel 電子表格,wxPython 網格類是wx.grid.Grid.
但是wx.grid.Grid 添加單元格數據比較麻煩,而且對於網格的控制也很少,爲此可以使用wx.grid.GridTableBase 類,該類是一個抽象類,開發人員需要實現該類一些方法。
wx.grid.GridTableBase 中需要被覆蓋的方法:
GetNumberCols() :
返回顯示在網格中的列的數目
GetNumberRows() :
返回顯示在網格中的行的數目
GetValue(row, col) :
返回單元格(row, col) 處的值
IsEmptyCell(row, col) :
如果座標(row, col) 處的單元格爲空的話,返回True 。否則返回False 。SetValue(row, col, value) :
該方法在當用戶編輯一個單元格時自動被調用。要得到一行或一列的標籤,使用GetColLabelValue(col) GetRowLabelValue(row) 方法。
import wx
import wx.grid
tableText = ["書籍編號", "書籍名稱", "作者", "出版社", "出版日期", "庫存數量"]
data = [["0036", "高等數學", "李放", "人民郵電出版社", "20000212", "1"],
["0004", "FLASH精選", "劉楊", "中國紡織出版社", "19990312", "2"],
["0025", "軟件工程", "牛田", "經濟科學出版社", "20000328", "4"],
["0015", "人工智能", "週末", "機械工業出版社", "19991223", "3"]]
class MyGridTable(wx.grid.GridTableBase):
def __init__(self):
super().__init__()
self.colLabels=tableText
def GetNumberRows(self):
return len(data)
def GetNumberCols(self):
return len(tableText)
def GetValue(self, row, col):
return data[row][col]
def GetColLabelValue(self, col):
return tableText[col]
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="網格控件",size=(500,200))
self.Center()
panel=wx.Panel(self)
grid=wx.grid.Grid(parent=panel)
table=MyGridTable()
grid.SetTable(table,True)
grid.AutoSize()
box=wx.BoxSizer()
box.Add(grid,flag=wx.ALL,border=10)
panel.SetSizer(box)
class App(wx.App):
def OnInit(self):
frame=MyFrame()
frame.Show()
return True
if __name__ =="__main__":
app=App()
app.MainLoop()
10. 分隔窗口
分隔窗口(wx.SplitterWindow) 就是將窗口分成兩部分,即分成左右或上下兩部分。如下圖所示窗口,整體上分爲左右兩個窗口,右窗口又分爲上下兩窗口,兩個窗口之間的分隔線是可以拖曳的,稱爲“窗框”(sash )。
在wxPython 中,分割窗是wx.SplitterWindow 的實例。
構造方法:
wx.SplitterWindow(parent, id=-1,pos=wx.DefaultPosition, size=wx.DefaultSize,style=wx.SP_3D, name="splitterWindow")
常用的方法:
(1 )SplitVertically(window1, window2, sashPosition=0):設置左右佈局的分隔窗口,window1 爲左窗口,window2 爲右窗口,sashPosition 是窗框的位置。
(2 )SplitHorizontally(window1, window2,sashPosition=0) :設置上下佈局的分隔窗口,window1 爲上窗口,window2 爲下窗口,sashPosition 是窗框的位置。
(3 )SetMinimumPaneSize(paneSize) :設置最小窗口尺寸。如果左右佈局,是指左窗口的最小尺寸;如果上下佈局,是指上窗口的最小尺寸。如果沒有設置則默認爲0.
import wx
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="分隔窗口控件",size=(350,180))
self.Center()
splitterr=wx.SplitterWindow(self,id=-1)
left=wx.Panel(splitterr)
right= wx.Panel(splitterr)
splitterr.SplitVertically(left, right, 100)
splitterr.SetMinimumPaneSize(80)
list=["蘋果","橘子","香蕉"]
listbox=wx.ListBox(parent=left,id=-1,choices=list,style=wx.LB_SINGLE)
vbox1=wx.BoxSizer(wx.VERTICAL)
vbox1.Add(listbox,1,flag=wx.ALL|wx.EXPAND,border=5)
left.SetSizer(vbox1)
text=wx.StaticText(parent=right,id=-1,label="右側面板")
vbox2=wx.BoxSizer(wx.VERTICAL)
vbox2.Add(text,1,flag=wx.ALL|wx.EXPAND,border=5)
right.SetSizer(vbox2)
class App(wx.App):
def OnInit(self):
frame=MyFrame()
frame.Show()
return True
if __name__=="__main__":
app=App()
app.MainLoop()
11. 消息對話框MessageDialog
構造函數:
wx.MessageDialog(parent, message, caption="Message box",style=wx.OK | wx.CANCEL, pos=wx.DefaultPosition)
按鈕樣式:
圖標樣式:
對話框通過使用ShowModal() 被調用。
四、事件處理
綁定是通過事件處理類的Bind() 方法實現的。
語法:
Bind(self, event, handler, source=None,id=wx.ID_ANY, id2=wx.ID_ANY)
event 是事件類型;
handler 是事件處理者(方法);
source 是事件源;
id 是事件源的標識;
id2 設置要綁定事件源的id 範圍;
如果不再需要事件處理時,最好調用事件處理類的Unbind() 方法解除綁定。
self.Bind(wx.EVT_BUTTON, self.on_click, id=10,id2=20)
最快的腳步不是跨越,而是繼續;最慢的步伐不是小步,而是徘徊。