GUI开发工具包
这些工具包较为突出的有: Tkinter、 PyQt 和 wxPython。
1. Tkinter
2. PyQt
3. wxPython
TKinter过于底层,PyQt过于庞大
wxPython 安装
1、 Windows 和 macOS 平台安装:
pip install -U wxPython
其中 install 是按照软件包, -U 是将指定软件包升级到最新版本。
2、 Linux 平台下使用 pip 安装有点麻烦,例如在 Ubuntu 16.04 安装,打开终端输入
如下指令:
pip install -U \
-f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-16.04 \
wxPython
3、下载 wxPython 帮助文档和案例。
https://extras.wxpython.org/wxPython4/extras
wxPython 基础
作为图形用户界面开发工具包 wxPython,主要提供了如下 GUI 内容:
1. 窗口。
2. 控件。
3. 事件处理。
4. 布局管理。
wxPython 类层次结构
第一个gui程序
语法一
# coding=utf-8
import wx
# 创建应用程序对象
app = wx.App()
# 创建窗口对象
frm = wx.Frame(None, title="第一个GUI程序!", size=(400, 300), pos=(100, 100))
# Frame类的源码 def __init__(self, parent=None, id=None, title=None, pos=None, size=None, style=None, name=None):
frm.Show() # 显示窗口
app.MainLoop() # 进入主事件循环
语法二
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title="第一个GUI程序!", size=(400, 300), pos=(100, 100))
# TODO
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
def OnExit(self):
print('应用程序退出')
return 0
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
界面构建层次
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title="第一个GUI程序!", size=(400, 300))
self.Centre() # 设置窗口居中
panel = wx.Panel(parent=self)
statictext = wx.StaticText(parent=panel, label='Hello World!', pos=(10, 10))
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
demo01
事件处理
简介
在事件处理的过程中涉及 4 个要素:
1. 事件。
2. 事件类型。
3. 事件源。
4. 事件处理者。
绑定是通过事件处理类的 Bind()方法实现, Bind()方法语法如下:
Bind(self, event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY)
自定义事件
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='一对一事件处理', size=(300, 180))
self.Centre() # 设置窗口居中
panel = wx.Panel(parent=self)
self.statictext = wx.StaticText(parent=panel, pos=(110, 20))
b = wx.Button(parent=panel, label='OK', pos=(100, 50))
self.Bind(wx.EVT_BUTTON, self.on_click, b)
def on_click(self, event):
print(type(event)) # <class 'wx._core.CommandEvent'>
self.statictext.SetLabelText('Hello, world.')
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
一对一
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='一对一事件处理', size=(300, 180))
self.Centre() # 设置窗口居中
panel = wx.Panel(parent=self)
self.statictext = wx.StaticText(parent=panel, pos=(110, 15))
b1 = wx.Button(parent=panel, id=10, label='Button1', pos=(100, 45))
b2 = wx.Button(parent=panel, id=12, label='Button2', pos=(100, 85))
# self.Bind(wx.EVT_BUTTON, self.on_click, b1)
# self.Bind(wx.EVT_BUTTON, self.on_click, id=11)
self.Bind(wx.EVT_BUTTON, self.on_click, id=10, id2=20) # id在[10,20]的触发self.on_click方法
def on_click(self, event):
event_id = event.GetId()
print(event_id)
if event_id == 10:
self.statictext.SetLabelText('Button1单击')
else:
self.statictext.SetLabelText('Button2单击')
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
一对多
内置事件
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title="鼠标事件处理", size=(400, 300))
self.Centre() # 设置窗口居中
self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down)
self.Bind(wx.EVT_LEFT_UP, self.on_left_up)
self.Bind(wx.EVT_MOTION, self.on_mouse_move)
def on_left_down(self, evt):
print('鼠标按下')
def on_left_up(self, evt):
print('鼠标释放')
def on_mouse_move(self, event):
if event.Dragging() and event.LeftIsDown():
pos = event.GetPosition()
print(pos)
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
鼠标事件
布局管理
使用绝对布局会有如下问题:
1. 子窗口(或控件)位置和大小不会随着父窗口的变化而变化。
2. 在不同平台上显示效果可能差别很大。
3. 在不同分辨率下显示效果可能差别很大。
4. 字体的变化也会对显示效果有影响。
5. 动态添加或删除子窗口(或控件)界面布局需要重新设计
布局分类
Box布局
简介
def Add(self, *__args): # real signature unknown; restored from __doc__ with multiple overloads
"""
Add(window, flags) -> SizerItem
Add(window, proportion=0, flag=0, border=0, userData=None) -> SizerItem
Add(sizer, flags) -> SizerItem
Add(sizer, proportion=0, flag=0, border=0, userData=None) -> SizerItem
Add(width, height, proportion=0, flag=0, border=0, userData=None) -> SizerItem
Add(width, height, flags) -> SizerItem
Add(item) -> SizerItem
Add(size, proportion=0, flag=0, border=0, /Transfer/=None) -> SizerItem
Add(size, flags) -> SizerItem
Appends a child to the sizer.
"""
return SizerItem
Add方法分类
flag参数
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='Box布局', size=(300, 120))
self.Centre() # 设置窗口居中
panel = wx.Panel(parent=self)
# 创建垂直方向Box布局管理器对象
vbox = wx.BoxSizer(wx.VERTICAL)
self.statictext = wx.StaticText(parent=panel, label='Button1单击')
# 添加静态文本到Box布局管理器
vbox.Add(self.statictext, proportion=2, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=10)
b1 = wx.Button(parent=panel, id=10, label='Button1')
b2 = wx.Button(parent=panel, id=11, label='Button2')
self.Bind(wx.EVT_BUTTON, self.on_click, id=10, id2=20)
# 创建水平方向的Box布局管理器对象
hbox = wx.BoxSizer(wx.HORIZONTAL)
# 添加b1到水平Box布局管理
hbox.Add(b1, 0, wx.EXPAND | wx.BOTTOM, 5)
# 添加b2到水平Box布局管理
hbox.Add(b2, 0, wx.EXPAND | wx.BOTTOM, 5)
# 将水平Box布局管理器到垂直Box布局管理器
vbox.Add(hbox, proportion=1, flag=wx.CENTER)
panel.SetSizer(vbox)
def on_click(self, event):
event_id = event.GetId()
print(event_id)
if event_id == 10:
self.statictext.SetLabelText('Button1单击')
else:
self.statictext.SetLabelText('Button2单击')
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
Box布局器demo
解析:1.statictext添加到vbox,2.button添加到hbox, 3.hbox添加到vbox. 4.vbox添加到panel
StaticBox布局
简介
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='StaticBox布局', size=(300, 120))
self.Centre() # 设置窗口居中
panel = wx.Panel(parent=self)
# 创建垂直方向的Box布局管理器对象
vbox = wx.BoxSizer(wx.VERTICAL)
self.statictext = wx.StaticText(parent=panel, label='Button1单击')
# 添加静态文本到Box布局管理器
vbox.Add(self.statictext, proportion=2, flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER, border=10)
b1 = wx.Button(parent=panel, id=10, label='Button1')
b2 = wx.Button(parent=panel, id=11, label='Button2')
self.Bind(wx.EVT_BUTTON, self.on_click, id=10, id2=20)
# 创建静态框对象
sb = wx.StaticBox(panel, label="按钮框")
# 创建水平方向的StaticBox布局管理器
hsbox = wx.StaticBoxSizer(sb, wx.HORIZONTAL)
# 添加b1到水平StaticBox布局管理
hsbox.Add(b1, 0, wx.EXPAND | wx.BOTTOM, 5)
# 添加b2到水平StaticBox布局管理
hsbox.Add(b2, 0, wx.EXPAND | wx.BOTTOM, 5)
# 添加hbox到vbox
vbox.Add(hsbox, proportion=1, flag=wx.CENTER)
panel.SetSizer(vbox)
def on_click(self, event):
event_id = event.GetId()
print(event_id)
if event_id == 10:
self.statictext.SetLabelText('Button1单击')
else:
self.statictext.SetLabelText('Button2单击')
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
StaticBox布局demo
解析: 把Box布中,hbox换成staticbox即可
Grid 布局
简介
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='Grid布局', size=(300, 300))
self.Centre() # 设置窗口居中
panel = wx.Panel(self)
btn1 = wx.Button(panel, label='1')
btn2 = wx.Button(panel, label='2')
btn3 = wx.Button(panel, label='3')
btn4 = wx.Button(panel, label='4')
btn5 = wx.Button(panel, label='5')
btn6 = wx.Button(panel, label='6')
btn7 = wx.Button(panel, label='7')
btn8 = wx.Button(panel, label='8')
btn9 = wx.Button(panel, label='9')
grid = wx.GridSizer(cols=3, rows=3, vgap=0, hgap=0)
# grid.AddMany([
# (btn1, 0, wx.EXPAND),
# (btn2, 0, wx.EXPAND),
# (btn3, 0, wx.EXPAND),
# (btn4, 0, wx.EXPAND),
# (btn5, 0, wx.EXPAND),
# (btn6, 0, wx.EXPAND),
# (btn7, 0, wx.EXPAND),
# (btn8, 0, wx.EXPAND),
# (btn9, 0, wx.EXPAND)
# ])
grid.Add(btn1, 0, wx.EXPAND)
grid.Add(btn2, 0, wx.EXPAND)
grid.Add(btn3, 0, wx.EXPAND)
grid.Add(btn4, 0, wx.EXPAND)
grid.Add(btn5, 0, wx.EXPAND)
grid.Add(btn6, 0, wx.EXPAND)
grid.Add(btn7, 0, wx.EXPAND)
grid.Add(btn8, 0, wx.EXPAND)
grid.Add(btn9, 0, 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() # 进入主事件循环
Grid布局demo
FlexGrid布局
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='FlexGrid布局', size=(400, 200))
self.Centre() # 设置窗口居中
panel = wx.Panel(parent=self)
fgs = wx.FlexGridSizer(3, 2, 10, 10)
title = wx.StaticText(panel, label="标题:")
author = wx.StaticText(panel, label="作者名:")
review = wx.StaticText(panel, label="内容:")
tc1 = wx.TextCtrl(panel)
tc2 = wx.TextCtrl(panel)
tc3 = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
fgs.AddMany([title, (tc1, 1, wx.EXPAND),
author, (tc2, 1, wx.EXPAND),
review, (tc3, 1, wx.EXPAND)])
fgs.AddGrowableRow(0, 1)
fgs.AddGrowableRow(1, 1)
fgs.AddGrowableRow(2, 3)
fgs.AddGrowableCol(0, 1)
fgs.AddGrowableCol(1, 2)
hbox = wx.BoxSizer(wx.HORIZONTAL) # hbox用于设置边框
hbox.Add(fgs, proportion=1, flag=wx.ALL | wx.EXPAND, border=15)
panel.SetSizer(hbox)
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
FlexGrid布局demo
控件
静态文本和按钮
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='静态文本和按钮', size=(300, 200))
self.Centre() # 设置窗口居中
panel = wx.Panel(parent=self)
# 创建垂直方向的Box布局管理器
vbox = wx.BoxSizer(wx.VERTICAL)
self.statictext = wx.StaticText(parent=panel, label='StaticText1', style=wx.ALIGN_CENTRE_HORIZONTAL)
b1 = wx.Button(parent=panel, label='OK')
self.Bind(wx.EVT_BUTTON, self.on_click, b1)
b2 = wx.ToggleButton(panel, -1, 'ToggleButton')
self.Bind(wx.EVT_BUTTON, self.on_click, b2)
bmp = wx.Bitmap('icon/1.png', wx.BITMAP_TYPE_PNG)
b3 = wx.BitmapButton(panel, -1, bmp)
self.Bind(wx.EVT_BUTTON, self.on_click, b3)
# 添加静态文本和按钮到Box布局管理器
vbox.Add(100, 10, proportion=1, flag=wx.CENTER | wx.FIXED_MINSIZE) # 添加空白空间
vbox.Add(self.statictext, proportion=1, flag=wx.CENTER | wx.FIXED_MINSIZE)
vbox.Add(b1, proportion=1, flag=wx.CENTER | wx.EXPAND)
vbox.Add(b2, proportion=1, flag=wx.CENTER | wx.EXPAND)
vbox.Add(b3, proportion=1, flag=wx.CENTER | wx.EXPAND)
panel.SetSizer(vbox)
def on_click(self, event):
self.statictext.SetLabelText('Hello, world.')
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
文本输入控件
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='文本框', size=(400, 200))
self.Centre() # 设置窗口居中
panel = wx.Panel(self)
hbox = wx.BoxSizer(wx.HORIZONTAL)
fgs = wx.FlexGridSizer(3, 2, 10, 10)
userid = wx.StaticText(panel, label="用户ID:")
pwd = wx.StaticText(panel, label="密码:")
content = wx.StaticText(panel, label="多行文本:")
tc1 = wx.TextCtrl(panel)
tc2 = wx.TextCtrl(panel, style=wx.TE_PASSWORD)
tc3 = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
# 设置tc1初始值
tc1.SetValue('tony')
# 获取tc1值
print('读取用户ID:{0}'.format(tc1.GetValue()))
fgs.AddMany([userid, (tc1, 1, wx.EXPAND),
pwd, (tc2, 1, wx.EXPAND),
content, (tc3, 1, wx.EXPAND)])
fgs.AddGrowableRow(0, 1)
fgs.AddGrowableRow(1, 1)
fgs.AddGrowableRow(2, 3)
fgs.AddGrowableCol(0, 1)
fgs.AddGrowableCol(1, 2)
hbox.Add(fgs, proportion=1, flag=wx.ALL | wx.EXPAND, border=15)
panel.SetSizer(hbox)
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
复选框和单选按钮
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='复选框和单选按钮', size=(400, 130))
self.Centre() # 设置窗口居中
panel = wx.Panel(self)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(panel, label='选择你喜欢的编程语言:')
cb1 = wx.CheckBox(panel, 1, 'Python')
cb2 = wx.CheckBox(panel, 2, 'Java')
cb2.SetValue(True)
cb3 = wx.CheckBox(panel, 3, 'C++')
self.Bind(wx.EVT_CHECKBOX, self.on_checkbox_click, id=1, id2=3)
hbox1.Add(statictext, 1, flag=wx.LEFT | wx.RIGHT | wx.FIXED_MINSIZE, border=5)
hbox1.Add(cb1, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox1.Add(cb2, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox1.Add(cb3, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(panel, label='选择性别:')
radio1 = wx.RadioButton(panel, 4, '男', style=wx.RB_GROUP)
radio2 = wx.RadioButton(panel, 5, '女')
self.Bind(wx.EVT_RADIOBUTTON, self.on_radio1_click, id=4, id2=5)
hbox2.Add(statictext, 1, flag=wx.LEFT | wx.RIGHT | wx.FIXED_MINSIZE, border=5)
hbox2.Add(radio1, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox2.Add(radio2, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox3 = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(panel, label='选择你最喜欢吃的水果:')
radio3 = wx.RadioButton(panel, 6, '苹果', style=wx.RB_GROUP)
radio4 = wx.RadioButton(panel, 7, '橘子')
radio5 = wx.RadioButton(panel, 8, '香蕉')
self.Bind(wx.EVT_RADIOBUTTON, self.on_radio2_click, id=6, id2=8)
hbox3.Add(statictext, 1, flag=wx.LEFT | wx.RIGHT | wx.FIXED_MINSIZE, border=5)
hbox3.Add(radio3, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox3.Add(radio4, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox3.Add(radio5, 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)
vbox.Add(hbox3, 1, flag=wx.ALL | wx.EXPAND, border=5)
panel.SetSizer(vbox)
def on_checkbox_click(self, event):
cb = event.GetEventObject()
print('选择 {0},状态{1}'.format(cb.GetLabel(), event.IsChecked()))
def on_radio1_click(self, event):
rb = event.GetEventObject()
print('第一组 {0} 被选中'.format(rb.GetLabel()))
def on_radio2_click(self, event):
rb = event.GetEventObject()
print('第二组 {0} 被选中'.format(rb.GetLabel()))
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
下拉列表
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='下拉列表', size=(400, 130))
self.Centre() # 设置窗口居中
panel = wx.Panel(self)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(panel, label='选择你喜欢的编程语言:')
list1 = ['Python', 'C++', 'Java']
ch1 = wx.ComboBox(panel, -1, value='C', choices=list1, style=wx.CB_SORT) # style=wx.CB_SORT 排序
self.Bind(wx.EVT_COMBOBOX, self.on_combobox, ch1)
hbox1.Add(statictext, 1, flag=wx.LEFT | wx.RIGHT | wx.FIXED_MINSIZE, border=5)
hbox1.Add(ch1, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(panel, label='选择性别:')
list2 = ['男', '女']
ch2 = wx.Choice(panel, -1, choices=list2)
self.Bind(wx.EVT_CHOICE, self.on_choice, ch2)
hbox2.Add(statictext, 1, flag=wx.LEFT | wx.RIGHT | wx.FIXED_MINSIZE, border=5)
hbox2.Add(ch2, 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)
def on_combobox(self, event):
print('选择 {0}'.format(event.GetString()))
def on_choice(self, event):
print('选择 {0}'.format(event.GetString()))
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
列表
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='下拉列表', size=(350, 180))
self.Centre() # 设置窗口居中
panel = wx.Panel(self)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(panel, label='选择你喜欢的编程语言:')
list1 = ['Python', 'C++', 'Java']
lb1 = wx.ListBox(panel, -1, choices=list1, style=wx.LB_SINGLE)
self.Bind(wx.EVT_LISTBOX, self.on_listbox1, lb1)
hbox1.Add(statictext, 1, flag=wx.LEFT | wx.RIGHT | wx.FIXED_MINSIZE, border=5)
hbox1.Add(lb1, 1, flag=wx.ALL | wx.FIXED_MINSIZE)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
statictext = wx.StaticText(panel, label='选择你喜欢吃的水果:')
list2 = ['苹果', '橘子', '香蕉']
lb2 = wx.ListBox(panel, -1, choices=list2, style=wx.LB_EXTENDED)
self.Bind(wx.EVT_LISTBOX, self.on_listbox2, lb2)
hbox2.Add(statictext, 1, flag=wx.LEFT | wx.RIGHT | wx.FIXED_MINSIZE, border=5)
hbox2.Add(lb2, 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)
def on_listbox1(self, event):
listbox = event.GetEventObject()
print('选择 {0}'.format(listbox.GetSelection()))
def on_listbox2(self, event):
listbox = event.GetEventObject()
print('选择 {0}'.format(listbox.GetSelections()))
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
静态图片控件
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='静态图片控件', size=(300, 300))
self.bmps = [wx.Bitmap('images/bird5.gif', wx.BITMAP_TYPE_GIF),
wx.Bitmap('images/bird4.gif', wx.BITMAP_TYPE_GIF),
wx.Bitmap('images/bird3.gif', wx.BITMAP_TYPE_GIF)]
self.Centre() # 设置窗口居中
self.panel = wx.Panel(parent=self)
# 创建垂直方向的Box布局管理器
vbox = wx.BoxSizer(wx.VERTICAL)
b1 = wx.Button(parent=self.panel, id=1, label='Button1')
b2 = wx.Button(self.panel, id=2, label='Button2')
self.Bind(wx.EVT_BUTTON, self.on_click, id=1, id2=2)
self.image = wx.StaticBitmap(self.panel, -1, self.bmps[0])
# 添加标控件到Box布局管理器
vbox.Add(b1, proportion=1, flag=wx.CENTER | wx.EXPAND)
vbox.Add(b2, proportion=1, flag=wx.CENTER | wx.EXPAND)
vbox.Add(self.image, proportion=3, flag=wx.CENTER)
self.panel.SetSizer(vbox)
def on_click(self, event):
event_id = event.GetId()
if event_id == 1:
self.image.SetBitmap(self.bmps[1])
else:
self.image.SetBitmap(self.bmps[2])
self.panel.Layout()
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
高级窗口
分隔窗口
wx.SplitterWindow 中一个常用的方法有:
import wx
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='分隔窗口', size=(350, 180))
self.Centre() # 设置窗口居中
splitter = wx.SplitterWindow(self, -1)
leftpanel = wx.Panel(splitter)
rightpanel = wx.Panel(splitter)
splitter.SplitVertically(leftpanel, rightpanel, 100)
splitter.SetMinimumPaneSize(80)
list2 = ['苹果', '橘子', '香蕉']
lb2 = wx.ListBox(leftpanel, -1, choices=list2, style=wx.LB_SINGLE)
self.Bind(wx.EVT_LISTBOX, self.on_listbox, lb2)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(lb2, 1, flag=wx.ALL | wx.EXPAND, border=5)
leftpanel.SetSizer(vbox1)
vbox2 = wx.BoxSizer(wx.VERTICAL)
self.content = wx.StaticText(rightpanel, label='右侧面板')
vbox2.Add(self.content, 1, flag=wx.ALL | wx.EXPAND, border=5)
rightpanel.SetSizer(vbox2)
def on_listbox(self, event):
s = '选择 {0}'.format(event.GetString())
self.content.SetLabel(s)
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
使用树
使用网格
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='网格控件', size=(550, 500))
self.Centre() # 设置窗口居中
self.grid = self.CreateGrid(self)
self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.OnLabelLeftClick)
def OnLabelLeftClick(self, event):
print("RowIdx:{0}".format(event.GetRow()))
print("ColIdx:{0}".format(event.GetCol()))
print(data[event.GetRow()])
event.Skip()
def CreateGrid(self, parent):
'表格初始化'
grid = wx.grid.Grid(parent)
grid.CreateGrid(len(data), len(data[0]))
for row in range(len(data)):
for col in range(len(data[row])):
grid.SetColLabelValue(col, column_names[col])
grid.SetCellValue(row, col, data[row][col])
# 设置行和列自定调整
grid.AutoSize()
return grid
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
语法一
class MyGridTable(wx.grid.GridTableBase):
def __init__(self):
super().__init__()
self.colLabels = column_names
def GetNumberRows(self):
return len(data)
def GetNumberCols(self):
return len(data[0])
def GetValue(self, row, col):
return data[row][col]
def GetColLabelValue(self, col):
return self.colLabels[col]
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='网格控件', size=(550, 500))
self.Centre() # 设置窗口居中
self.grid = self.CreateGrid(self)
self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.OnLabelLeftClick)
def OnLabelLeftClick(self, event):
print("RowIdx:{0}".format(event.GetRow()))
print("ColIdx:{0}".format(event.GetCol()))
print(data[event.GetRow()])
event.Skip()
def CreateGrid(self, parent):
grid = wx.grid.Grid(parent)
tablebase = MyGridTable()
grid.SetTable(tablebase, True)
# 设置行和列自定调整
grid.AutoSize()
return grid
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
语法二
菜单栏
import wx
import wx.grid
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='使用菜单', size=(550, 500))
self.Centre() # 设置窗口居中
self.text = wx.TextCtrl(self, -1, style=wx.EXPAND | wx.TE_MULTILINE)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.text, proportion=1, flag=wx.EXPAND | wx.ALL, border=1)
self.SetSizer(vbox)
menubar = wx.MenuBar()
file_menu = wx.Menu()
new_item = wx.MenuItem(file_menu, wx.ID_NEW, text="新建", kind=wx.ITEM_NORMAL)
self.Bind(wx.EVT_MENU, self.on_newitem_click, id=wx.ID_NEW)
file_menu.Append(new_item)
file_menu.AppendSeparator()
edit_menu = wx.Menu()
copy_item = wx.MenuItem(edit_menu, 100, text="复制", kind=wx.ITEM_NORMAL)
edit_menu.Append(copy_item)
cut_item = wx.MenuItem(edit_menu, 101, text="剪切", kind=wx.ITEM_NORMAL)
edit_menu.Append(cut_item)
paste_item = wx.MenuItem(edit_menu, 102, text="粘贴", kind=wx.ITEM_NORMAL)
edit_menu.Append(paste_item)
self.Bind(wx.EVT_MENU, self.on_editmenu_click, id=100, id2=102)
file_menu.Append(wx.ID_ANY, "编辑", edit_menu)
menubar.Append(file_menu, '文件')
self.SetMenuBar(menubar)
def on_newitem_click(self, event):
self.text.SetLabel('单击【新建】菜单')
def on_editmenu_click(self, event):
event_id = event.GetId()
if event_id == 100:
self.text.SetLabel('单击【复制】菜单')
elif event_id == 101:
self.text.SetLabel('单击【剪切】菜单')
else:
self.text.SetLabel('单击【粘贴】菜单')
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
工具栏
import wx
import wx.grid
# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='使用工具栏', size=(550, 500))
self.Centre() # 设置窗口居中
self.Show(True)
self.text = wx.TextCtrl(self, -1, style=wx.EXPAND | wx.TE_MULTILINE)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.text, proportion=1, flag=wx.EXPAND | wx.ALL, border=1)
self.SetSizer(vbox)
menubar = wx.MenuBar()
file_menu = wx.Menu()
new_item = wx.MenuItem(file_menu, wx.ID_NEW, text="新建", kind=wx.ITEM_NORMAL)
file_menu.Append(new_item)
file_menu.AppendSeparator()
edit_menu = wx.Menu()
copy_item = wx.MenuItem(edit_menu, 100, text="复制", kind=wx.ITEM_NORMAL)
edit_menu.Append(copy_item)
cut_item = wx.MenuItem(edit_menu, 101, text="剪切", kind=wx.ITEM_NORMAL)
edit_menu.Append(cut_item)
paste_item = wx.MenuItem(edit_menu, 102, text="粘贴", kind=wx.ITEM_NORMAL)
edit_menu.Append(paste_item)
file_menu.Append(wx.ID_ANY, "编辑", edit_menu)
menubar.Append(file_menu, '文件')
self.SetMenuBar(menubar)
# 工具栏
# 创建工具栏对象
tb = wx.ToolBar(self, wx.ID_ANY)
self.ToolBar = tb
tsize = (24, 24)
new_bmp = wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR, tsize)
open_bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize)
copy_bmp = wx.ArtProvider.GetBitmap(wx.ART_COPY, wx.ART_TOOLBAR, tsize)
paste_bmp = wx.ArtProvider.GetBitmap(wx.ART_PASTE, wx.ART_TOOLBAR, tsize)
tb.AddTool(10, "New", new_bmp, kind=wx.ITEM_NORMAL, shortHelp="New")
tb.AddTool(20, "Open", open_bmp, kind=wx.ITEM_NORMAL, shortHelp="Open")
tb.AddSeparator()
tb.AddTool(30, "Copy", copy_bmp, kind=wx.ITEM_NORMAL, shortHelp="Copy")
tb.AddTool(40, "Paste", paste_bmp, kind=wx.ITEM_NORMAL, shortHelp="Paste")
tb.AddSeparator()
tb.AddTool(201, "back", wx.Bitmap("menu_icon/back.png"), kind=wx.ITEM_NORMAL, shortHelp="Back")
tb.AddTool(202, "forward", wx.Bitmap("menu_icon/forward.png"), kind=wx.ITEM_NORMAL, shortHelp="Forward")
self.Bind(wx.EVT_MENU, self.on_click, id=201, id2=202)
tb.AddSeparator()
tb.Realize()
def on_click(self, event):
event_id = event.GetId()
if event_id == 201:
self.text.SetLabel('单击【Back】按钮')
else:
self.text.SetLabel('单击【Forward】按钮')
class App(wx.App):
def OnInit(self):
# 创建窗口对象
frame = MyFrame()
frame.Show()
return True
if __name__ == '__main__':
app = App()
app.MainLoop() # 进入主事件循环
View Code
GUI开发IDE
wxFormBuilder
建议:
1.wxFormBuilder设计界面
2.后端逻辑代码建议用另一个文件继承UI代码的MyFrame类
GUI设计