Advertisement

Python大佬手把手教你利用wxPython模块编写界面程序

阅读量:

wxPython是一个用于开发桌面端图形界面的应用程序或应用程序的跨平台函数库,并且其编程语言为Python。它以C++为基础构建了一个基于wxWidgets的函数库包装层。

很多学习者在Python编程中都面临着找不到入门路径的问题。
掌握基本语法后仍感到困惑的学习者们,在寻找实践资源来开始学习时往往无从下手。
那些已经完成了一些案例项目的技术爱好者们,在系统地深入提升自己的技术能力方面同样存在挑战。
为了满足不同层次的学习需求...免费领取视频教程...课程资源!
帮助各类学习者快速成长!

wxpython有大量组件,它们可以从逻辑上(注意是逻辑上)这样划分:

(1)基础组件

这些组件为其所派生的子组件提供基础功能,通常不直接使用。

(2)顶层组件

这些组件相互独立存在。

(3)容器

这些组件包含其他组件。

(4)动态组件

这些组件可以被用户所交互编辑。

(5)静态组件

这些组件用来展示信息,无法被用户所交互编辑。

(6)其他组件

这些组件包括状态栏、工具栏、菜单栏等。

除了基于逻辑的分类之外,在各个层级中各组件间还存在继承关系;例如在一个按钮组件中就体现了这一特点

Button属于一类小窗口。它属于一类称为wx.Control的小窗口(值得注意的是,并非所有window组件都源自于此类别;例如,在某些情况下会有例外)。更具体地说, controls这样的组件能够放置在containers这样的容器之上。每一个window都可以响应事件,因此bottom按钮也具备这一特征——并且还继承了其父类属性——即wx.EvtHandler的能力。此外,所有的Python wx对象都源自于一个基础类——wx.Object类

wxPython的“你好世界”

这个例子是wxPython的最小可用例子,用来say hello to the world:

复制代码

麻雀虽小五脏俱全,该例子包含了最基本的代码和组件:

(1)首先导入wxPython库:

复制代码

wx可视为一个命名空间,后面所有的函数和类都以它开头。

(2)创建应用实例:

复制代码

每一个wxPython程序都必须有一个应用实例。

(3)创建应用框架并显示:

复制代码

我们创建了一个wx.Frame对象。这是一个关键性的'容器'组件,在此框架中我们可以容纳其他各种元素。 wx.Frame本身不具备父级关系(除非我们将parent属性设置为None),这意味着如果希望将此组件作为根元素使用,则无需指定父级关系。 通过调用Show方法我们可以使该框架成为可见界面元素。

wx.Frame的构造函数一共有七个参数:

复制代码

然而第一个parent参数必须明确指定;而其余六个参数均具有默认设置:具体涉及ID编号、名称标识符以及位置信息等基本属性。因此而言,在进一步优化该frame之前,请考虑调整这些参数以实现更加个性化的配置。

(4)启动程序主循环:

复制代码

主循环机制遵循持续不断运行的状态,并负责收集与分配与程序生命周期相关的所有事件

菜单栏和工具栏

菜单栏

菜单栏主要由三部分组成:wx.MenuBar、wx.Menu和wx.MenuItem。

在MenuBar中支持设置一个菜单,在其下新增菜单项

添加完后不要忘了使用SetMenuBar来将菜单栏加入到框架中。

此外,在某个菜单Menu中,还可以添加子菜单SubMenu,并接着继续添加菜单项

除了安装标志和快捷方式外,还可以对菜单进行以下设置:首先定义对wx.EVTMENU事件的响应方式;其次,在菜单样式中选择是否以勾选或单选形式显示

上下文菜单

上下文菜单有时叫做“弹出菜单”,比如右键某个位置,出现上下文选项。

工具栏

在创建过程中遵循相同步骤:首先按照指定流程创建主菜单栏CreateMenuBar;随后在主菜单栏中新增功能模块AddFunctionModule

请记住启用toolbar.Realize()以便使其显现出来(此步骤与操作系统的兼容性有关,在Linux系统中并非强制要求而在Windows系统则必须采用该方法以确保跨平台兼容)

该工具能够配置相应的逻辑来实现启用或禁用功能。常见实例如undo和redo功能键。这些按钮通常无法在所有情况下被点击。在初始状态下,默认情况下redoc按钮会被禁用。这是因为没有历史操作记录的缘故。因此可以通过设定特定的逻辑来实现这一点

状态栏

状态栏即底部显示当前状态的状态条。

布局管理

布局可以分为绝对布局和布局管理器sizer。绝对布局有很多缺点,比如:

(1)组件的尺寸和位置不随窗口的改变而改变;

(2)不同平台上应用程序可能显示不同;

(3)字体的改变可能破坏布局;

(4)如果想改变布局,必须将之前的全部推翻。

因此,推荐使用布局管理器sizer来管理布局。

在wxPython中常用的布局器包括:BoxSizer、StaticBoxSizer、GridSizer、FlexGridSiner和GridBagSiner。

wx.BoxSizer

wx.BoxSizer是最常见的布局管理器。它的常用设置有:

(1)排列方向:wx.VERTICAL垂直排列还是wx.HORIZONTAL水平排列;

(2)排列比例:布局中的各个组件大小由指定的比例值决定;其中当比例设置为0时,则该组件的大小将不受窗口缩放的影响;而其他的比例系数则表示各组件在布局管理器中所占的比例份额;此外,在实际应用中我们通常会配置wx.EXPAND标志以确保组件能够充分扩展至管理器提供的可用区域。

(3)边界:组件对象的边界尺寸可被定制化配置;同时,在上、下、左、右或全部边域中任选其一作为操作范围。

(4)排列方式:可设置为左侧边缘居左、右侧边缘居右、顶端居上、底端居下以及居中排列等多种排列方式;

(5)在某一级容器组件中,使用SetSizer()来为其指定布局管理器;

(6)在布局管理器中用Add()方法来添加组件。

wx.StaticBoxSizer是在BoxSizer周围加上了一个静态文本框的显示。

wx.GridSizer

该网格布局管理器使用wx.GridSizer实现其功能,在配置时可设定行数和列数以及水平和垂直间距,并且所有组件的大小完全一致。

(若某些网格无需添加组件,则可添加无内容的StaticText用于占位)

wx.FlexGridSizer

FlexGridSizer类似于wx.GridSizer但更加灵活它不仅不需要网格中所有单元尺寸一致而且在同一行内的各个单元高度一致同时在同一列内的各个单元宽度一致。

它还可以配置可扩展的行与列,并在现有布局中有可用空间时优化指定的行与列以适应可用的空间(建议确保相关组件具有expandable属性)

wx.GridBagSizer

GridBagSizer是wxPython框架中最灵活使用的布局管理器(不仅限于wxPython),它允许明确分配布局管理器中的组件位置。例如可以根据需要安排组件跨越多行或多列。

它的构造函数很简单:

复制代码

只需设定间距,然后通过Add()方法添加组件:

复制代码

pos参数决定了组件在虚拟网格中的起始位置,(0, 0)意味着左上角(span则决定了组件占据的行数和列数),例如(3, 2)表示占据三行两列。

如果想组件可以随窗口伸缩,别忘了设置expandle属性,及:

复制代码

Sizer常见问题

大部分的问题出现在:

(1)在设定proportional属性时出现错误的情况是:只有当组件或sizer的大小会根据窗口变化时才需将proportional属性设为非0值;否则应将其设为0值。需要注意的是:每个sizer及其内部的组件都可以独立配置其proportional属性参数

复制代码

在vbox容器中新增了一个hbox1容器,在其内部增加了两个元素:一个是静态文本框st1组件(用于显示固定信息),另一个是输入框tc字段(接收用户输入)。特别地,在这个hbox1容器内部设置了动态布局属性:将hbox1的比例值设为0(表示该容器的高度不受父级垂直管理器的影响),而tc字段被设置为比例值为1(即占满其父级容器宽度)。这种设计使得系统能够根据不同的垂直管理器状态维持稳定的布局表现:当垂直管理器发生变化时(如高度增减),hbox1的尺寸保持不变;而tc字段则会随之其父级水平容器宽度的变化自动调整大小。这种灵活的布局机制赋予了系统极高的适应性,在不同场景下都能提供良好的用户体验

(总结起来:看是否expandable要看组件所在的sizer!!)

(2)边界border尺寸设置不统一,导致对不齐

可扩展性属性与比例设置两个参数中有一个未被正确配置,影响组件无法适应窗口的缩放需求

这个sizer的编写此处可借助WX Form Builder工具来进行设计, 所思即所得.(WX Form Builder具备即时更改的能力, 然而在此场景下遇到了个小问题: 在WX GridBagSizer设置了某列进行伸缩后, 在WX Form Builder环境中却无法正确应用这种设置. 然而生成代码后再直接调用则能正常应用这种设置. 因此也不完全依赖于它, 但仍然有99%的信心. 若实在无法调通, 可尝试更换运行方式继续排查.)

事件

事件

事件作为图形界面程序的主要组成部分,并且所有图形界面程序都以事件驱动的方式运行。

事件包含多种产生途径, 其中大部分是由用户引发的操作. 此外还可能存在由其他机制导致的情况. 例如网络连接涉及窗口管理以及计时器调用来执行操作.

关于事件,这里面有几个过程和要素:

该程序采用wxPython框架中的标准开发流程,在其核心实现中设置了基于事件循环的主循环机制(MainLoop()方法)。这个主循环持续不断地搜索并捕获各种特定事件(如wx.EVT_SIZE表示窗口缩放事件、wx.EVT_CLOSE表示窗口关闭事件等)。一旦捕捉到某个特定的 wx 事件类型时,则会立即触发相应的响应动作(如窗口缩放、窗口关闭等)。接着系统会通过分发机制将该特定 wx 事件分配并发送给相应的响应动作执行者(即所谓的 Event Handler),而这一过程则完全依赖于绑定机制负责处理(即通过调用Bind()方法建立事件与响应动作之间的映射关系)。

对用户编程来说,最常打交道的就是Bind()方法:

复制代码

源自该EvtHandler类内部对其进行了方法定义,在其继承关系中存在一个派生的Window类结构,默认情况下该Window类可作为绝大多数组件的基础架构配置选项(若需要解除与其绑定关系,则应调用对应的Unbind()方法操作,在此过程中其所需处理参数与下面部分完全一致)。

event参数就是事件对象,它指定了事件类型;

handler就是对该事件的响应方法,这个通常要由编程自定义完成;

source标识该事件的来源组件,在wxPython中可以通过指定source参数来明确绑定到特定组件上

该id基于ID字段来指定事件来源;则source字段则是以实例形式直接指定。两者的目的相同;组件id主要有以下几种创建方式:

由系统自动分配:其中一种方法是利用-1或wx.ID_ANY标识符,在这种情况下系统会自动生成一个负整数值作为对象标识码。需要注意的是,默认情况下生成的对象标识码均为负值;而用户的自定义对象则应为正整数值以避免冲突;在无需修改组件状态的情形下通常采用此方式以保持原有配置的一致性;可以通过调用GetId()函数来获取该隐藏标识码以供后续操作使用

(2)标准ID:wxPython提供了一些标准IDs,比如wx.ID_SAVE、wx.ID_NEW等;

id2是指定多个IDs,上面的id是一次只能指定单个ID。

其中有一个非常有趣的特性是可以实现批量绑定多个同类组件事件的功能。

复制代码

事件传播

分为两种类型的事件:basic events与command events。它们之间的主要区别在于是否涉及传播机制。当一个组件触发特定事件时,会将这一请求传递给其父级组件以便进行响应处理。基本事件不会进行这种传递流程而command event则会进行传输。例如,在wx中CloseEvent属于基本事件的一种类型它不会向父级组件传输数据因为这样做并无实际意义

在默认情况下,在事件句柄中设置的事件被设计为阻止信息传播。如果希望该事件能够持续传播下去,则可以通过调用skip()方法来实现这一目标。这进一步揭示了与前面提到的方法之间的区别

常见事件

窗口移动事件:wx.EVT_MOVE

在软件工程领域中定义了窗口销毁事件:wx.EVT_CLOSE这一特定的中断类型,在程序执行过程中当用户触发关闭操作时会被检测到这一中断事件(注意该事件的处理应采用Python程序实现destroy()函数)

按钮事件:wx.EVT_BUTTON,点击一个按钮时

菜单事件:wx.EVT_MENU,点击一个菜单时

绘图相关事件:wx.EVT_PAINT,在调整窗口大小或将其最大化时(而当将窗口最小化时则不会触发此事件)

焦点事件:wx.EVT_SET_FOCUS, 当某个组件成为焦点时;wx.EVT_KILL_FOCUS, 当某个组件失去焦点时

键盘事件:当按下键时触发的事件为wx.EVT_KEY_DOWN;当键被释放时触发的事件为wx.EVT_KEY_UP;在处理字符输入时使用的是wx.EVT_CHAR事件类型

对话框

对话框是人机交互中一种关键性的界面工具,通过允许用户进行数据输入、数据修改以及程序配置调整等功能。

预定义的消息对话框

消息对话框旨在向用户提供消息展示功能。用户可以通过预先提供的标志设置来自定义按钮布局和图标设计。具体操作可通过下图进行查看。

自定义对话框

若想自定义对话框,只需继承wx.Dialog即可。

常用组件

基础组件

wxPython提供了大量基础组件,如:

基础按钮Button;

图形按钮BitmapButton;

切换按钮ToggleButton(有两种状态可以切换:按下和未按下);

静态文本框StaticText(展示一行或多行只读文本);

文本输入框TextCtrl;

富文本输入框RichTextCtrl可以加入图像、文字色彩等效果;

带格式文本输入框StyledTextCtrl;

超链接HyperLinkCtrl;

静态位图:StaticBitmap;

静态分割线StaticLine(可垂直可水平);

静态框StaticBox(为了装饰用,将多个组件组合在一起显示);

下拉列表框ComboBox;

可编辑的下拉列表框Choice;

复选框CheckBox(有两个状态:勾选或未勾选);

radio button type RadioButton(radio buttons are designed to allow users to select only one option at a time; when multiple radio buttons are grouped together, you can achieve this by setting the style of the first radio button to wx.RB_GROUP; the subsequent radio buttons will automatically join this group; to create a new group, simply set the style of the first radio button in that group to wx.RB_GROUP);

进度条Gauge;

滑动条Slider;

整数数值调节钮SpinCtrl;

浮点数数值调节钮SpinCtrlDouble;

滚动条ScrollBar。

高级组件

列表框ListBox:是一种用于呈现一组选项并实现操作交互的对象;它包含两个核心事件:当用户单击某一选项时触发的第一个事件(对应于wx.EVT_COMMAND_LISTBOX_SELECTED);以及当用户对某一选项执行双键点击操作时触发的第二个事件(对应于wx.EVT_COMMAND_LISTBOX_DOUBLE_CLICKED)。

列表视图中的ListCtrl也用于展示一组选项,在其设计上与标准的ListBox存在显著差异。与ListBox仅限于显示单列不同的是,ListCtrl能够同时展示多个视图模式包括列表视图、报表视图以及图标视图等。向该控件中添加数据需要采用两种不同的方法首先通过调用InsertItem()方法获取当前行号随后再在当前行中利用SetItem()方法将数据插入到相应的列中。

Mixins:该库增加了ListCtrl的功能,并将所有Mixins都包含在wx.lib.mixins.listctrl这个模块内。总共有六个不同的Mixins:

(1)wx.ColumnSorterMixin:使得在report视图中对列进行排序;

wx.ListCtrlAutoWidthMixin:该控件能够自适应地调整最后一列区域的宽度以填充剩余空间;

(3)wx.ListCtrlSelectionManagerMix:定义了与系统无关的选择策略;

(4)wx.TextEditMixin:使得可以编辑文本;

(5)wx.CheckListCtrlMixin:给每一行增加了一个复选框;

(6)wx.ListRowHighlighter:候选行自动背景高亮。

wx.html.HtmlWindow:用来展示HTML页面。

wx_SPLITTERWINDOW:由两块子窗口区域构成(当采用WXFORMBUILDER时,请确保手动增加两块_PANEL)

另外还有比如:

树状结构TreeCtrl;

表格Grid;

搜索框SearchCtrl;

调色板ColourPickerCtrl;

字体设置器FontPickerCtrl;

文件选择器FilePickerCtrl;

文件目录选择器DirPickerCtrl;

文件树选择器GenericDirCtrl;

日期选择器DatePickerCtrl;

日历CalenderCtrl。

绘图

wxPython的绘图之前写过,参见以下两篇:

ImagePy深入分析:6 — 基于wxPython的图形绘制与浮点画布工具

ImagePy解析:11 — 使用wxPython设备上下文绘图

自定义组件

正如所述,在wxPython中现有的常用组件种类繁多且数量充足。然而这些现有的常用组件依然无法满足真实场景中的各种复杂需求。这时候需要根据个人需求来定制组件以应对这些问题。

自定义组件有两种开发策略:其一是基于现有组件进行调整或优化;其二是利用wxPython的GDI功能模块进行开发

从头绘制组件一般都是在wx.Panel基础上进行创建。

俄罗斯方块

下面展示了俄罗斯方块的游戏程序源代码,并且可以看出它是一个利用wxPython开发GUI界面程序的经典案例:

复制代码

效果如图:

不过我在运行上述代码时遇到了问题,在控制方块的过程中无法使用箭头键,在Board panel中详细说明了设置方法:

复制代码

该问题的讨论在:

如何捕获箭头键?(http://wxpython-users.1045709.n5.nabble.com/how-to-catch-arrow-keys-td2365210.html)

遇到使用箭头键或Tab键时会失去键盘焦点的问题

另外,捕获keycode,如果是判断字母,最好是大小写形式都判断,即里面:

复制代码

全部评论 (0)

还没有任何评论哟~