使用 wxPython 创建 GUI 程序的三个主要步骤。
(1)导入 wxPython 包。
(2)建立框架类。
(3)建立主程序。
9.1.1 Frame
Frame 也称为框架或窗体,是所有框架的父类,也是包含标题栏、菜单、按钮等其他控件的容器,运行之后可移动、缩放。
wxPython GUI 框架 代码示例:
import wx
class MyFrame(wx.Frame):
def __init__(self, superior):
wx.Frame.__init__(self, parent = superior, title = u'My First Form', size = (300, 300))
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_MOVE, self.OnFrameMove)
#
panel = wx.Panel(self, -1)
label1 = wx.StaticText(panel, -1, "FrameSize:")
label2 = wx.StaticText(panel, -1, "FramePos:")
label3 = wx.StaticText(panel, label = "MousePos:")
self.sizeFrame = wx.TextCtrl(panel, -1, "", style = wx.TE_READONLY)
self.posFrame = wx.TextCtrl(panel, -1, "", style = wx.TE_READONLY)
self.posMouse = wx.TextCtrl(panel, -1, "", style = wx.TE_READONLY)
panel.Bind(wx.EVT_MOTION, self.OnMouseMove) # 绑定事件处理函数
self.panel = panel
#
sizer = wx.FlexGridSizer(3, 2, 5, 5)
sizer.Add(label1)
sizer.Add(self.sizeFrame)
sizer.Add(label2)
sizer.Add(self.posFrame)
sizer.Add(label3)
sizer.Add(self.posMouse)
border = wx.BoxSizer()
border.Add(sizer, 0, wx.ALL, 15)
panel.SetSizerAndFit(border)
self.Fit()
def OnSize(self, event):
size = event.GetSize()
self.sizeFrame.SetValue("%s, %s"%(size.width, size.height))
#
event.Skip()
def OnFrameMove(self, event):
pos = event.GetPosition()
self.posFrame.SetValue("%s, %s"%(pos.x, pos.y))
def OnMouseMove(self, event):
pos = event.GetPosition()
self.posMouse.SetValue("%s, %s"%(pos.x, pos.y))
if __name__ == '__main__':
app = wx.App()
frame = MyFrame(None)
frame.Show(True)
app.MainLoop()
9.1.2 Button、StaticText、TextCtrl
按钮绑定事件处理函数方法。
Bind(event, handle, source = None, id1 = -1, id2 = -2)
静态文本框用来显示文本,不要来响应用户单击或双击事件。
素数判断的 GUI 程序。
import wx
from math import sqrt
class IsPrimeFrame(wx.Frame):
def __init__(self, superion):
wx.Frame.__init__(self, parent = superion, title = 'Check Prime', size = (400, 200))
panel = wx.Panel(self)
panel.SetBackgroundColour('Yellow') # 设置窗体颜色
wx.StaticText(parent = panel, label = 'Input a integer:', pos = (10, 10)) # 添加静态文本控件
self.inputN = wx.TextCtrl(parent = panel, pos = (120, 10)) # 添加文本框
self.result = wx.StaticText(parent = panel, label = '', pos = (10, 50))
self.buttonCheck = wx.Button(parent = panel, label = 'Check', pos = (70, 90)) # 添加按钮
# 为按钮绑定事件
self.Bind(wx.EVT_BUTTON, self.OnButtonCheck, self.buttonCheck)
self.buttonQuit = wx.Button(parent = panel, label = 'Quit', pos = (150, 90))
self.Bind(wx.EVT_BUTTON, self.OnButtonQuit, self.buttonQuit)
def OnButtonCheck(self, event):
self.result.SetLabel('')
try:
num = int(self.inputN.GetValue()) # 获取输入的数字
except BaseException as e:
self.result.SetLabel('not a integer')
return
n = int(sqrt(num))
for i in range(2, n +1):
if num % i == 0:
self.result.SetLabel('NO') # 用静态文本框显示结果
break
else:
self.result.SetLabel('Yes')
def OnButtonQuit(self, event):
dig = wx.MessageDialog(self, 'Really Quit?', 'Caution', wx.CANCEL|wx.OK|wx.ICON_QUESTION)
if dig.ShowModal() == wx.ID_OK:
self.Destroy()
if __name__ == '__main__':
app = wx.App()
frame = IsPrimeFrame(None)
frame.Show()
app.MainLoop()
运行结果:
9.1.3 Menu
创建普通菜单。
import wx
class Menu(wx.Frame):
def __init__(self, superion):
wx.Frame.__init__(self, parent = superion, title = 'wxGUI', size = (640, 480))
self.panel = wx.Panel(self, -1)
self.menuBar = wx.MenuBar() # 创建菜单栏
self.menu = wx.Menu() # 创建菜单
self.menuOpen = self.menu.Append(101, 'Open') # 创建菜单项
self.menuSave = self.menu.Append(102, 'Save')
self.menuSaveAs = self.menu.Append(103, 'Save As')
self.menu.AppendSeparator()
self.menuClose = self.menu.Append(104, 'Close')
self.menuBar.Append(self.menu, '&File') # 将菜单添加至菜单栏
self.menu = wx.Menu()
self.menuCopy = self.menu.Append(201, 'Copy')
self.menuCut = self.menu.Append(202, 'Cut')
self.menuPaste = self.menu.Append(202, 'Paste')
self.menuBar.Append(self.menu, '&Edit')
self.SetMenuBar(self.menuBar)
if __name__ == '__main__':
app = wx.App()
frame = Menu(None)
frame.Show()
app.MainLoop()
创建弹出式菜单。
self.popupMenu = wx.Menu()
self.popupCopy = self.popupMenu.Append(901, 'Copy')
self.popupCut = self.popupMenu.Append(902, 'Cut')
self.popupPaste = self.popupMenu.Append(903, 'Paste')
self.panel.Bind(wx.EVT_RIGHT_DOWN, self.OnRClick)
编写右键单击处理函数。
def OnRClick(self, event):
pos = (event.GetX(), event.GetY())
self.panel.PopupMenu(self.popupMenu, pos)
为菜单项绑定单击处理函数。
wx.EVT_MENU(self, 104, self.OnClose)
def OnClose(self, event):
self.statusBar.SetStatusText('You clicked the menu')
9.1.4 ToolBar、StatusBar
(1)创建工具栏。
self.toolbar = self.frame.CreateToolBar()
在工具栏添加工具。
self.toolbar.AddSimpleTool()
下面的代码使工具栏生效。
self.toolbar.Realize()
最后绑定事件处理函数。
wx.EVT_TOOL(self, 999, self.OnOpen)
(2)创建状态栏。
self.statusBar = self.frame.CreateStatusBar()
可以在状态栏显示状态或文本以提示用户。
self.statusBar.SetStatusText('You clicked the Open menu.')
9.1.5 对话框
wxPython 提供了一整套预定义的对话框,常用的有:
(1)MessageBox。
(2)GetTextFromUser---接收用户输入的文本。
(3)GetPasswordFromUser---接收用户输入的密码。
(4)GetNumberFromUser。
(5)FileDialog---文件对话框。
(6)FontDialog---字体对话框。
(7)ColourDialog---颜色对话框。
演示交互模式下颜色对话框。
>>> import wx
>>> app = wx.App()
>>> dlg = wx.ColourDialog(None)
>>> dlg.ShowModal()
5101
>>> c = dlg.GetColourData()
>>> c
<wx._core.ColourData object at 0x03B603D0>
>>> c.Colour
wx.Colour(0, 0, 0, 255)
9.1.6 RadioButton、CheckBox
单选框和复选框的用法。
import wx
class wxGUI(wx.App):
def OnInit(self):
self.frame = wx.Frame(parent = None, title = 'wxGUI', size = (300, 280))
self.panel = wx.Panel(self.frame, -1)
self.radioButtonSexM = wx.RadioButton(self.panel, -1, 'Male', pos = (80, 60))
self.radioButtonSexF = wx.RadioButton(self.panel, -1, 'Female', pos = (80, 80))
self.checkBoxAdmin = wx.CheckBox(self.panel, -1, 'Aministrator', pos = (150, 80))
self.label1 = wx.StaticText(self.panel, -1, 'UserName:', pos = (0, 110), style = wx.ALIGN_RIGHT)
self.label2 = wx.StaticText(self.panel, -1, 'UserName:', pos = (0, 130), style = wx.ALIGN_RIGHT)
self.textName = wx.TextCtrl(self.panel, -1, pos = (70, 110), size = (160, 20))
self.textPwd = wx.TextCtrl(self.panel, -1, pos = (70, 130), size = (160, 20), style = wx.TE_PASSWORD)
self.buttonOK = wx.Button(self.panel, -1, 'OK', pos = (30, 160))
self.Bind(wx.EVT_BUTTON, self.OnButtonOK, self.buttonOK)
self.buttonCancel = wx.Button(self.panel, -1, 'Cancel', pos = (120, 160))
self.Bind(wx.EVT_BUTTON, self.OnButtonCancel, self.buttonCancel)
self.buttonOK.SetDefault()
self.frame.Show()
return True
def OnButtonOK(self, event):
finalStr = ''
if self.radioButtonSexM.GetValue() == True:
finalStr += 'Sex:Male\n'
elif self.radioButtonSexF.GetValue() == True:
finalStr += 'Sex:Female\n'
if self.checkBoxAdmin.GetValue() == True:
finalStr += 'Administrator\n'
if self.textName.GetValue() == 'dfg' and self.textPwd.GetValue() == '88888888':
finalStr += 'user name and password are correct.\n'
else:
finalStr += 'user name or password is incorrect.\n'
wx.MessageBox(finalStr)
def OnButtonCancel(self, event):
self.radioButtonSexM.SetValue(True) # 设置为选中状态
self.radioButtonSexF.SetValue(False) # 设置为未选中状态
self.checkBoxAdmin.SetValue(True)
self.textName.SetValue('')
self.textPwd.SetValue('')
app = wxGUI()
app.MainLoop()
运行结果:
9.1.7 ComBoBox
复选框可以使用 wx.EVT_COMBOBOX() 为组合绑定事件处理函数。
import wx
class ComboBox(wx.App):
def OnInit(self):
self.frame = wx.Frame(parent = None, title = 'wxGUI', size = (300, 200))
self.panel = wx.Panel(self.frame, -1)
self.names = {'First Class':['Zhang San', 'Li Si', 'Wang Wu'], 'Second Class':['Zhao liu', 'Zhou Qi']}
# ComboBox1
self.comboBox1 = wx.ComboBox(self.panel, value = 'Click here', choices = list(self.names.keys()),\
pos = (0, 50), size = (100, 30))
self.Bind(wx.EVT_COMBOBOX, self.OnCombo1, self.comboBox1)
# ComboBox2
self.comboBox2 = wx.ComboBox(self.panel, value = 'Click here', choices = [],\
pos = (0, 100), size = (100, 30))
self.Bind(wx.EVT_COMBOBOX, self.OnCombo2, self.comboBox2)
self.frame.Show()
return True
def OnCombo1(self, event):
banji = self.comboBox1.GetValue()
self.comboBox2.Set(self.names[banji])
def OnCombo2(self, event):
wx.MessageBox(self.comboBox2.GetValue())
app = ComboBox()
app.MainLoop()
运行结果:
9.1.8 ListBox
列表框用来放置多个元素提供用户进行选择,每个元素都是字符串,支持单选和多选。
列表框应用:
import wx
class ListBoxDemo(wx.Frame):
def __init__(self, superion):
wx.Frame.__init__(self, parent = superion, title = 'ListBox demo', size = (200, 200))
panel = wx.Panel(self)
self.buttonQuit = wx.Button(parent = panel, label = 'Quit', pos = (60, 120))
self.Bind(wx.EVT_BUTTON, self.OnButtonQuit, self.buttonQuit)
li = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
self.listBox = wx.ListBox(panel, choices = li) # 创建列表框
self.Bind(wx.EVT_LISTBOX, self.OnClick, self.listBox) # 绑定事件处理函数
def OnClick(self, event):
#
s = self.listBox.GetStringSelection()
wx.MessageBox(s)
def OnButtonQuit(self, event):
dig = wx.MessageDialog(self, 'Really Quit?', 'Caution', wx.CANCEL|wx.OK|wx.ICON_QUESTION)
if dig.ShowModal() == wx.ID_OK:
self.Destroy()
if __name__ == '__main__':
app = wx.App()
frame = ListBoxDemo(None)
frame.Show()
app.MainLoop()
运行结果:
9.1.9 TreeCtrl
树形控件用来显示有严格层次关系的数据,非常清晰地表示各元素之间的从属关系。
树形控件应用:
import wx
class TreeCtrlFrame(wx.Frame):
def __init__(self, superion):
wx.Frame.__init__(self, parent = superion, title = 'TreeCtrl demo', size = (300, 400))
panel = wx.Panel(self)
self.tree = wx.TreeCtrl(parent = panel, pos = (5, 5), size = (120, 200))
self.inputString = wx.TextCtrl(parent = panel, pos = (150, 10))
self.buttonAddChild = wx.Button(parent = panel, label = 'AddChild', pos = (150, 90))
self.Bind(wx.EVT_BUTTON, self.OnButtonAddChild, self.buttonAddChild)
self.buttonDeleteNode = wx.Button(parent = panel, label = 'DeleteNode', pos = (150, 120))
self.Bind(wx.EVT_BUTTON, self.OnButtonDeleteNode, self.buttonDeleteNode)
self.buttonAddRoot = wx.Button(parent = panel, label = 'AddRoot', pos = (150, 150))
self.Bind(wx.EVT_BUTTON, self.OnButtonAddRoot, self.buttonAddRoot)
def OnButtonAddChild(self, event):
itemSelected = self.tree.GetSelection()
if not itemSelected:
wx.MessageBox('Select a Node first!')
return
itemString = self.inputString.GetValue()
self.tree.AppendItem(itemSelected, itemString)
def OnButtonDeleteNode(self, event):
itemSelected = self.tree.GetSelection()
if not itemSelected:
wx.MessageBox('Select a Node first!')
return
self.tree.Delete(itemSelected)
def OnButtonAddRoot(self, event):
rootItem = self.tree.GetRootItem()
if rootItem:
wx.MessageBox('The tree has already a root.')
else:
itemString = self.inputString.GetValue()
self.tree.AddRoot(itemString)
if __name__ == '__main__':
app = wx.App()
frame = TreeCtrlFrame(None)
frame.Show()
app.MainLoop()
运行结果: