一、介绍

官网:https://wxpython.org/
安装:pip install -U wxPython
image.png

二、创建应用程序

应用程序对象管理主事件循环,主事件循环时wxPython程序的动力,如果没有应用程序对象,wxPython应用程序将不能运行。
顶级窗口通常用于管理最重要的数据,控制并呈现给用户。
image.png

2.1 创建一个wx.App的子类

步骤:
1.定义子类
2.在这个子类中写一个OnInit() 初始化方法
3.在程序的主要部分创建这个类的一个实例
4.调用应用程序实例的MainLoop() 方法

  1. import wx ##导入wxPython
  2. class App(wx.App):
  3. def OnInit(self): ##初始化方法
  4. frame = wx.Frame(parent=None,title="Hello wxPython! ") ##创建窗口
  5. frame.Show() ##显示窗口
  6. return True ##返回值
  7. if __name__ == "__main__":
  8. app = App() ##调用APP类的实例
  9. app.MainLoop() ##调用APP类的MainLoop()主循环方法

image.png

2.2 直接使用wx.App

通常,如果在系统中只有一个窗口的话,可以不创建wx.App子类,直接使用wx.App,这个类提供了一个最基本的OnInit() 初始化的方法。

  1. import wx ##导入wxPython
  2. app = wx.App() ##初始化wx.App类
  3. frame = wx.Frame(None,title="Hello wxPython !") ##定义一个顶级窗口
  4. frame.Show() ##显示窗口
  5. app.MainLoop() ##调用wx.App类的MainLoop() 主循环方法

image.png

2.3 使用wx.Frame框架

在GUI中,框架也称为窗口,框架是一个容器,用户可以将它在屏幕上任意移动,并可将它进行缩放,通常包含标题栏、菜单等。
在wxPython中,wx.Frame是所有框架的父类,当用户创建wx.Framw的子类的时候,子类应该调用其父类的构造器wx.Frame.init()。
wx.Frmae的构造器语法格式:
wx.Frame(parent,id = 1,title= " ",pos = wx.DefaultPosition,size = wx.DefaultSize,style=wx.DEFAULT_FRAME_STYLE,name = "frame")
parent:框架的父窗口,如果是顶级窗口,这个值是None
id:关于新窗口的wxPythonID号,通常设置为-1,让wxPython自动生成一个新的ID
title:窗口的标题
pos:一个wx.Point对象,它指定这个新窗口的左上角在屏幕中的位置,在图形用户界面程序中,通常(0,0)是显示器的左上角。默认为(-1,-1)让系统决定窗口的位置
size:一个wx.Size对象,它指定这个窗口的初始尺寸,这个默认的(-1,-1) 将让系统决定窗口的初始尺寸
style:指定窗口的类型的变量,可以使用或运算来组合它们
name:框架的内在的名字,可以使用它来寻找这个窗口

  1. ##使用wx.Frame 框架
  2. import wx ##导入wxPython
  3. class MyFrame(wx.Frame):
  4. def __init__(self,parent,id):
  5. wx.Frame.__init__(self,parent,id,title="创建 Frame",pos= (100,100),size =(300,300))
  6. if __name__ == "__main__":
  7. app = wx.App() ##初始化应用
  8. frame = MyFrame(parent = None,id=1) ##实例MyFrame类,并传递参数
  9. frame.Show() ##显示窗口
  10. app.MainLoop() ##调用MainLoop()主循环方法

image.png

三、常用控件

3.1 StaticText 文本类

wx.StaticText类来完成屏幕上绘制纯文本
语法: wx.StaticText(parnet,id,label,pos=wx.DefaulPosition,size=wx.DefaultSize,style=0,name="StaticText"
parent:父窗口部件
id:标识符,使用-1可以自动创建一个唯一的标识
label:显示在静态控件中的文本内容
pos:一个wx.Point对象或一个python元组,窗口部件的位置
size:一个wx.Size对象或一个python元组,窗口部件的大小
style:样式标记
name:对象的名字
设置字体的语法
wx.font(pointSize,family,style,weight,underline=Flase,faceNme="",enconding = wx.FONTENCONDING_DEFAULT)
pointSize:字体的整数尺寸,单位为磅
family:用于快速指定一个字体而无须知道该字体的实际名字
style:指明字体是否倾斜
weight:指明字体的醒目程度
underline:只在windows下面有效,值为True,加下划线,值为False,不加下划线
faceNme:指定字体名
enconding:指定编码方式,不指定为默认编码方式

  1. ##静态文本输出
  2. import wx
  3. class MyFrame(wx.Frame):
  4. def __init__(self, parent,id):
  5. wx.Frame.__init__(self, parent,id,title = '创建静态文本类',pos = (100,100),size =(600,450))
  6. panel = wx.Panel(self) ##创建画板
  7. ##创建标题,并设置字体
  8. title = wx.StaticText(panel,label ="Python 之禅 ----Tim Peters",pos=(100,20))
  9. font = wx.Font(16,wx.DEFAULT,wx.FONTSTYLE_NORMAL,wx.NORMAL)
  10. title.SetFont(font)
  11. ##创建文本
  12. wx.StaticText(panel,label ="Beautiful is better than ugly.",pos=(50,50))
  13. wx.StaticText(panel,label ="Explicit is better than implicit.",pos=(50,70))
  14. wx.StaticText(panel,label ="Simple is better than complex.",pos=(50,90))
  15. wx.StaticText(panel,label ="Complex is better than complicated.",pos=(50,110))
  16. wx.StaticText(panel,label ="Flat is better than nested.",pos=(50,130))
  17. wx.StaticText(panel,label ="Sparse is better than dense.",pos=(50,150))
  18. wx.StaticText(panel,label ="Readability counts.",pos=(50,170))
  19. wx.StaticText(panel,label ="Special cases aren't special enough to break the rules.",pos=(50,190))
  20. wx.StaticText(panel,label ="Although practicality beats purity.",pos=(50,210))
  21. wx.StaticText(panel,label ="Errors should never pass silently.",pos=(50,230))
  22. wx.StaticText(panel,label ="Unless explicitly silenced.",pos=(50,250))
  23. wx.StaticText(panel,label ="In the face of ambiguity, refuse the temptation to guess.",pos=(50,270))
  24. wx.StaticText(panel,label ="There should be one-- and preferably only one --obvious way to do it.",pos=(50,290))
  25. wx.StaticText(panel,label ="Although that way may not be obvious at first unless you're Dutch.",pos=(50,310))
  26. wx.StaticText(panel,label ="If the implementation is hard to explain, it's a bad idea.",pos=(50,330))
  27. wx.StaticText(panel,label ="If the implementation is easy to explain, it may be a good idea.",pos=(50,350))
  28. wx.StaticText(panel,label ="Namespaces are one honking great idea -- let's do more of those!",pos=(50,370))
  29. if __name__ == "__main__":
  30. app= wx.App() #初始化应用
  31. frame = MyFrame(parent=None,id = -1) #实例化MyFrame类,并传递参数
  32. frame.Show() #显示窗口
  33. app.MainLoop() #调用主循环方法

image.png

3.2 TextCtrl输入文本类

wx.TextCtrl类允许输入单行和多行文本,也可以作为密码输入控件。
语法格式:wx.TextCtrl(parant,id,vlaue="",pos=wx.DefaultPosition,size=wx.DefaultSize,style=0,validator=wx.DefaultValidatorname=wx.TextCtrlNameStr)
style:单行wx.TextCtrl的格式

  1. - wx.TE_CENTER:控件中的文本居中
  2. - wx.TE_LEFT:控件中的文本左对齐,默认行为。
  3. - wx.TE_NOHIDESEL:文本始终高亮显示,只适用于Windows
  4. - wx.TE_PASSWORD:不显示所键入的文本,代替以星号显示。
  5. - wx.TE_PROCESS_ENTER:如果使用了这个样式,那么当用户在控件内按下回车

键时,一个文本输入事件被触发。否则,按键事件内在的由该文本控件或该对话框管

  1. - wx.TE_PROCESS_TAB:如果指定了这个样式,那么通常的字符事件在Tab键按下

时创建(一般意味一个制表符将被插入文本)。否则,tab由对话框来管理,通常是
控件间的切换

  1. - wx.TE_READONLY:文本控件为只读,用户不能修改其中的文本。
  2. - wx.TE_RIGHT:控件中的文本右对齐。

vlaue:显示在该控件中的初始文本
validator:常用于过滤数据以确保只能输入要接收的数据

  1. import wx
  2. class MyFrame(wx.Frame):
  3. def __init__(self, parent,id):
  4. wx.Frame.__init__(self, parent,id,title="创建TextCtrl类",size = (400,300))
  5. #创建面板
  6. panel = wx.Panel(self)
  7. #创建文本和输入框
  8. self.title = wx.StaticText(panel,label ="请输入用户名和密码",pos = (140,20))
  9. self.label_user = wx.StaticText(panel,label ="用户名",pos = (50,50))
  10. self.text_user = wx.TextCtrl(panel,pos = (100,50),size =(235,25),style = wx.TE_LEFT)
  11. self.label_password = wx.StaticText(panel,label="密码",pos = (50,90))
  12. self.text_password = wx.TextCtrl(panel,pos = (100,90),size =(235,25),style = wx.TE_PASSWORD)
  13. if __name__ == "__main__":
  14. app = wx.App() ##初始化应用
  15. frame = MyFrame(parent = None,id = 1) ##实例化MyFrame类,并传递参数
  16. frame.Show() ##显示窗口
  17. app.MainLoop() ##调用主循环方法

image.png image.png

3.3 Button 按钮类

按钮用于捕获用户生成的单击事件,用于触发绑定的处理函数。
语法:
wx.Button(parent, id, label, pos, size=wxDefaultSize, style=0,validator, name="button"

  1. import wx
  2. class MyFrame(wx.Frame):
  3. def __init__(self, parent,id):
  4. wx.Frame.__init__(self, parent,id,title="创建TextCtrl类",size = (400,300))
  5. #创建面板
  6. panel = wx.Panel(self)
  7. #创建文本和输入框
  8. self.title = wx.StaticText(panel,label ="请输入用户名和密码",pos = (140,20))
  9. self.label_user = wx.StaticText(panel,label ="用户名",pos = (50,50))
  10. self.text_user = wx.TextCtrl(panel,pos = (100,50),size =(235,25),style = wx.TE_LEFT)
  11. self.label_password = wx.StaticText(panel,label="密码",pos = (50,90))
  12. self.text_password = wx.TextCtrl(panel,pos = (100,90),size =(235,25),style = wx.TE_PASSWORD)
  13. ##创建确定和取消按钮
  14. self.bt_confirm = wx.Button(panel,pos = (105,130),label="确定")
  15. self.bt_cancel = wx.Button(panel,pos = (195,130),label="取消")
  16. if __name__ == "__main__":
  17. app = wx.App() ##初始化应用
  18. frame = MyFrame(parent = None,id = 1) ##实例化MyFrame类,并传递参数
  19. frame.Show() ##显示窗口
  20. app.MainLoop() ##调用主循环方法

image.png

四、Sizer

sizer是用于自动布局一组窗口控件的算法,属于一个容器窗口,每个不同的sizer基于一套规则管理它的窗口的尺寸和位置。

创建一个siezer的步骤:
1.创建用来自动调动尺寸的panel或container(容器)
2.创建sizer
3.创建子窗口
4.使用sizer的Add() 方法来将每个子窗口添加到sizer,并添加sizer的附加信息,eg:窗口周围控件的度量,如何对齐窗口,当容器窗口改变大小的时候如何拓展子窗口
5.sizer可以嵌套,可以添加别的sizer到父sizer中
6.调用容器的SetSizer(sizer)方法

常用的wxPython的sizer

sizer名称 描述
BoxSizer 在一条线上的窗口部件的布局,可以是水平或垂直的
当尺寸改变的时候,控制窗口部件的行为上很灵活,通常用于嵌套的样式
FlexGridSizer 网格布局,行和列所在行或列的最大元素分别被设置
GridSizer 网格布局,每个元素都有相同的尺寸
项目被从左到右添加,直到一行被填满,然后从下一行开始
GridBagSizer 网格布局,允许项目被放置在网格上的特定点,也允许项目跨越多个网格区域
StaticBoxSizer 等同于wx.BoxSizer,多了一个边框,带有标题和环线

4.1 box sizer

box sizer是wxPython提供的sizer中的最简单和最灵活的sizer。
一个box sizer是一个垂直列或水平行,窗口部件在其中从左至右或从上到下布置在一条线上。

实例

  1. #使用BoxSizer布局
  2. import wx
  3. class MyFrame(wx.Frame):
  4. def __init__(self, parent,id):
  5. wx.Frame.__init__(self, parent,id,'用户登录',size = (400,300))
  6. ##创建面板
  7. panel = wx.Panel(self)
  8. self.title = wx.StaticText(panel,label ="请输入用户名和密码")
  9. #添加容器
  10. vsizer = wx.BoxSizer(wx.VERTICAL) ##创建了一个wx.BoxSizer
  11. vsizer.Add(self.title,proportion=0,flag=wx.BOTTOM|wx.TOP|wx.ALIGN_CENTER,border = 15) ##设置增加背景控件,
  12. panel.SetSizer(vsizer)
  13. if __name__ == "__main__":
  14. app = wx.App() ##初始化
  15. frame = MyFrame(parent=None,id=-1) ##实例MyFrame,并传递参数
  16. frame.Show() ##显示窗口
  17. app.MainLoop() ##调用主循环方法

image.png

Add() 使用语法
Box.Add(control,propotion,flag,border)
control:要添加的控件
proportion:所添加控件在定义的定位方式所代表方向上占据的控件比例。
flag:flag参数与border参数结合使用可以指定边距宽度

  1. - wx.LFET:左边距
  2. - wx.RIGHT:右边距
  3. - wx.BOTTOM:下边距
  4. - wx.TOP:上边距
  5. - wx.ALL:上下左右四个边距
  6. - wx.ALIGN_LFET:左边对齐
  7. - wx.ALIGN_RIGHT:右边对齐
  8. - wx.ALIGN_TOP:顶部对齐
  9. - wx.ALIGN_BOTTOM:底边对齐
  10. - wx.ALIGN_CENTER_VERTICAL:垂直对齐
  11. - wx.ALIGN_CENTER_HORIZONTAL:水平对齐
  12. - wx.ALIGN_CENTER:居中对齐
  13. - wx.EXPAND:所添加控件将占有sizer定位方向上所有可用的空间
  14. - boder:控制所添加控件的边距

实现用户登录界面
image.png

  1. ##实现用户登录界面
  2. import wx
  3. class MyFrame(wx.Frame):
  4. def __init__(self,parent,id):
  5. wx.Frame.__init__(self,parent,id,'用户登录',size=(400,300))
  6. ##创建面板
  7. panel = wx.Panel(self)
  8. ##创建"确定”和“取消”按钮
  9. self.bt_button = wx.Button(panel,label="确定")
  10. self.cacel_button = wx.Button(panel,label="取消")
  11. ##创建“文本,左对齐
  12. self.static_Text = wx.StaticText(panel,label="请输入用户名和密码")
  13. self.Suser_Text = wx.StaticText(panel,label="用户名")
  14. self.user_Text = wx.TextCtrl(panel,style=wx.TE_LEFT)
  15. self.Spass_Text = wx.StaticText(panel,label="密码")
  16. self.pass_Text = wx.TextCtrl(panel,style= wx.TE_PASSWORD,)
  17. ##添加容器,容器中控件横向对齐
  18. hsizer_user = wx.BoxSizer(wx.HORIZONTAL)
  19. hsizer_user.Add(self.Suser_Text,proportion=0,flag=wx.ALL,border=5)
  20. hsizer_user.Add(self.user_Text,proportion=1,flag=wx.ALL,border=5)
  21. hsizer_pass = wx.BoxSizer(wx.HORIZONTAL)
  22. hsizer_pass.Add(self.Spass_Text,proportion=0,flag=wx.ALL,border=5)
  23. hsizer_pass.Add(self.pass_Text,proportion=1,flag=wx.ALL,border=5)
  24. hsizer_Button = wx.BoxSizer(wx.HORIZONTAL)
  25. hsizer_Button.Add(self.bt_button,proportion=0,flag=wx.ALIGN_CENTER,border=5)
  26. hsizer_Button.Add(self.cacel_button,proportion=1,flag=wx.ALIGN_CENTER,border=5)
  27. ##添加容器,容器中控件纵向对齐
  28. vsizer_all = wx.BoxSizer(wx.VERTICAL)
  29. vsizer_all.Add(self.static_Text,proportion=0,flag=wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM,border=15)
  30. vsizer_all.Add(hsizer_user,proportion=1,flag=wx.LEFT|wx.RIGHT|wx.EXPAND,border=45)
  31. vsizer_all.Add(hsizer_pass,proportion=2,flag=wx.LEFT|wx.RIGHT|wx.EXPAND,border=45)
  32. vsizer_all.Add(hsizer_Button,proportion=3,flag=wx.ALIGN_CENTER|wx.TOP,border=15)
  33. panel.SetSizer(vsizer_all)
  34. if __name__ == "__main__":
  35. app = wx.App()
  36. frame = MyFrame(parent=None,id=-1)
  37. frame.Show()
  38. app.MainLoop()

五、事件处理

事件(event)是指应用程序期间发生的时候,要求有一个响应。
事件处理器(event hander):响应事件时所调用的函数或方法。
事件绑定器(event binder):封装了特定窗口部件、特定事件类型和一个事件处理器的wxPython对象。

编写事件处理器语法:
self.Bind(wx.EVT_BUTTON, self.OnClick, aButton)
Bind() 方法是wx.EvtHandle的一个方法,声明为按钮事件类型
self.OnClick是方法名
image.pngimage.png

image.png

  1. ##实现用户登录界面
  2. import wx
  3. class MyFrame(wx.Frame):
  4. def __init__(self,parent,id):
  5. wx.Frame.__init__(self,parent,id,'用户登录',size=(400,300))
  6. ##创建面板
  7. panel = wx.Panel(self)
  8. ##创建"确定”和“取消”按钮
  9. self.bt_button = wx.Button(panel,label="确定")
  10. self.bt_button.Bind(wx.EVT_BUTTON,self.OnClickBt)
  11. self.cacel_button = wx.Button(panel,label="取消")
  12. self.cacel_button.Bind(wx.EVT_BUTTON,self.OnClickCancel)
  13. ##创建“文本,左对齐
  14. self.static_Text = wx.StaticText(panel,label="请输入用户名和密码")
  15. self.Suser_Text = wx.StaticText(panel,label="用户名")
  16. self.user_Text = wx.TextCtrl(panel,style=wx.TE_LEFT)
  17. self.Spass_Text = wx.StaticText(panel,label="密码")
  18. self.pass_Text = wx.TextCtrl(panel,style= wx.TE_PASSWORD,)
  19. ##添加容器,容器中控件横向对齐
  20. hsizer_user = wx.BoxSizer(wx.HORIZONTAL)
  21. hsizer_user.Add(self.Suser_Text,proportion=0,flag=wx.ALL,border=5)
  22. hsizer_user.Add(self.user_Text,proportion=1,flag=wx.ALL,border=5)
  23. hsizer_pass = wx.BoxSizer(wx.HORIZONTAL)
  24. hsizer_pass.Add(self.Spass_Text,proportion=0,flag=wx.ALL,border=5)
  25. hsizer_pass.Add(self.pass_Text,proportion=1,flag=wx.ALL,border=5)
  26. hsizer_Button = wx.BoxSizer(wx.HORIZONTAL)
  27. hsizer_Button.Add(self.bt_button,proportion=0,flag=wx.ALIGN_CENTER,border=5)
  28. hsizer_Button.Add(self.cacel_button,proportion=1,flag=wx.ALIGN_CENTER,border=5)
  29. ##添加容器,容器中控件纵向对齐
  30. vsizer_all = wx.BoxSizer(wx.VERTICAL)
  31. vsizer_all.Add(self.static_Text,proportion=0,flag=wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM,border=15)
  32. vsizer_all.Add(hsizer_user,proportion=1,flag=wx.LEFT|wx.RIGHT|wx.EXPAND,border=45)
  33. vsizer_all.Add(hsizer_pass,proportion=2,flag=wx.LEFT|wx.RIGHT|wx.EXPAND,border=45)
  34. vsizer_all.Add(hsizer_Button,proportion=3,flag=wx.ALIGN_CENTER|wx.TOP,border=15)
  35. panel.SetSizer(vsizer_all)
  36. ##单击确定的事件处理
  37. def OnClickBt(self,event):
  38. message = " "
  39. username = self.user_Text.GetValue() ##获取输入的用户名
  40. password = self.pass_Text.GetValue() ##获取输入的密码
  41. if username == "" or password == "":
  42. message ='用户名或密码不能为空'
  43. elif username == 'lhuan' and password == 'lhuan':
  44. message = '登录成功'
  45. else:
  46. message = '用户名和密码不匹配'
  47. wx.MessageBox(message)
  48. ##单击取消的事件处理
  49. def OnClickCancel(self,event):
  50. self.user_Text.SetValue("") ##清空输入的用户名
  51. self.pass_Text.SetValue("") ##清空输入的密码
  52. if __name__ == "__main__":
  53. app = wx.App()
  54. frame = MyFrame(parent=None,id=-1)
  55. frame.Show()
  56. app.MainLoop()