python【第十二篇】 图形界面编程之wxPython
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() # 进入主事件循环
界面构建层次
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
事件处理
简介
在事件处理的过程中涉及 4 个要素: 1. 事件。 2. 事件类型。 3. 事件源。 4. 事件处理者。 绑定是通过事件处理类的 Bind()方法实现, Bind()方法语法如下: Bind(self, event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY)
自定义事件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
内置事件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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布局
简介
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
flag参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
解析:1.statictext添加到vbox,2.button添加到hbox, 3.hbox添加到vbox. 4.vbox添加到panel
StaticBox布局
简介
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
解析: 把Box布中,hbox换成staticbox即可
Grid 布局
简介
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
FlexGrid布局
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
控件
静态文本和按钮
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
文本输入控件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
复选框和单选按钮
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
下拉列表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
列表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
静态图片控件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
高级窗口
分隔窗口
wx.SplitterWindow 中一个常用的方法有:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
使用树
使用网格
![](https://img2020.cnblogs.com/blog/795445/202005/795445-20200531155927693-1211065032.png)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 自定义窗口类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() # 进入主事件循环
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
菜单栏
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
工具栏
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() # 进入主事件循环
GUI开发IDE
wxFormBuilder
建议:
1.wxFormBuilder设计界面
2.后端逻辑代码建议用另一个文件继承UI代码的MyFrame类
GUI设计
谢谢