Python:界面开发,wx入门篇

news2024/10/6 6:44:18

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/3Yb_YAKiMte_f5HanetXiA

本文大概 3617 个字,阅读需花 10 分钟
内容不多,但也花了一些精力
如要交流,欢迎评论区留言
谢谢你的点赞收藏分享

如果你接触过桌面 GUI 软件开发,那么你一定会对 MFC、WPF、Qt 等有或多或少的了解。

那么什么是 GUI 软件呢?GUI 软件是带有用户交互界面的软件,有按钮,有窗口,还有很多其它用于和用户交互的小部件。常见的例子是,比如各个厂家推出的浏览器,上面有标签,有按钮,有网址输入栏,有网页内容展示窗口和状态栏等等。

不过,这里打算为大家介绍一下使用 Python 怎么去做 GUI 开发,因为会 Python 的人更多,相信其中也有很多人对开发界面软件颇有兴趣。好,看下文。

Python 的 GUI 开发框架有好几种,比较主流的有 wxPython、PyQt、Tkinter,这三种都是跨平台方案。

wxPython 是 Python 的第三方库,代码实现基于 C++ 的 wxWidgets 库封装,呈现的界面风格和系统本地风格一致。其许可协议规定如果直接引用 wxPython 的二进制库文件,则可以随便使用。

可以看看在 linux 系统下基于 wxPython 的界面程序是什么样子

在这里插入图片描述

PyQt 是 Qt 平台的 Python 版本,自绘的界面风格,许可协议对商业应用不太友好。虽然和原生风格已经很接近了,但还是有人能挑出刺来。

可以看看在 linux 系统下基于 PyQt 的界面程序是什么样子

在这里插入图片描述

Tkinter 是 Python 自带的 GUI 开发框架,也是本地化风格。

看看在 linux 系统下基于 Tkinter 的界面,风格真的有些过时了

在这里插入图片描述

值得一提的是,wxPython 也是 Python 作者主推的 GUI 开发框架。

今天先讲 wxPython,至于其它方案,会在后边的其它推文讲解,敬请关注。

环境配置

由于 VSCODE 的开放性和插件生态极其丰富的原因,推荐基于 VSCODE 来搭建开发环境。

本文以下内容基于 windows 10 和 Python3.

开发 Python 工程之前,先配置一个虚拟环境。

在 VSCODE 里打开选好的工程存放目录,然后点击 VSCODE 顶部菜单栏 Terminal -> New Terminal,弹出命令行终端,输入

python -m venv .venv

启动虚拟环境

.venv\Scripts\activate.bat

安装 wxPython

先查看一下当前环境里已经预装了哪些工具包

pip list

Output:

Package    Version
---------- -------
pip        21.1.1
setuptools 56.0.0
WARNING: You are using pip version 21.1.1; however, version 22.3.1 is available.
You should consider upgrading via the '.\.venv\scripts\python.exe -m pip install --upgrade pip' command.

建议升级一下 pip

python -m pip install --upgrade pip

Output:

Requirement already satisfied: pip in .\.venv\lib\site-packages (21.1.1)
Collecting pip
  Using cached pip-22.3.1-py3-none-any.whl (2.1 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 21.1.1
    Uninstalling pip-21.1.1:
      Successfully uninstalled pip-21.1.1
Successfully installed pip-22.3.1

安装 wxPython 包

pip install wxpython

Output:

Collecting wxpython
  Using cached wxPython-4.2.0-cp38-cp38-win_amd64.whl (18.0 MB)
Collecting pillow
  Using cached Pillow-9.3.0-cp38-cp38-win_amd64.whl (2.5 MB)
Collecting numpy
  Using cached numpy-1.23.5-cp38-cp38-win_amd64.whl (14.7 MB)
Collecting six
  Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: six, pillow, numpy, wxpython
Successfully installed numpy-1.23.5 pillow-9.3.0 six-1.16.0 wxpython-4.2.0

再查看一下实际都安装了哪些工具包

Package    Version
---------- -------
numpy      1.23.5
Pillow     9.3.0
pip        22.3.1
setuptools 56.0.0
six        1.16.0
wxPython   4.2.0

看到,wxpython 其实还依赖了 numpy、Pillow、six 这几个包。

基本程序

先来看一看一个基本的 wxPython GUI 程序骨架,新建文件 main.py,输入以下内容并保存。

// main.py

import wx

app = wx.App()
window = wx.Frame(parent=None, title="hello Python GUI APP!")
window.Show()
app.MainLoop()

导入 wx 库,也就是 wxPython 库,首先实例化类 wx.App

wx.App 类代表着整个应用,被用于引导 wxPython 系统,初始化底层的 gui 工具包,设置或者获取应用级别的属性,实现本机窗口系统的主消息或者事件环,以及分派事件到各个窗口实例等。每个 wx 应用都必须有且仅有一个 wx.App 类实例,而且为了确保 gui 平台和小部件都被初始化完成,所有 UI 对象的创建必须在 wx.App 类实例创建之后。为了实现更复杂的初始化过程,可以对 wx.App 类执行派生,然后重写方法 OnInit,窗口初始化完成时会调用方法 OnInit

然后,创建 wx.Frame 类实例,初始化时,设置父窗口为空和设置标题为 hello Python GUI APP!

wx.Frame 是用户可以改变大小和位置的窗口类,调用 Show() 显示窗口。

wxPython 提供了非常丰富的窗口部件(widget)和辅助控件来简化复杂 GUI 的开发过程。基本的 widget 比如有输入框 TextCtrl,按键 Button,静态文本 StaticText,菜单栏 MenuBar,列表 ListCtrl等。简单的辅助控件比如有布局器 BoxSizer,菜单 Menu等。为了显示丰富的内容,除了可以直接使用框架提供的窗口部件,还可以对这些部件派生以添加更多功能。

最后,调用类 wx.App 对象的 MainLoop() 方法来启动主界面的事件环,这时候用户和界面交互才会有反应。

输入指令以执行程序

python main.py

在这里插入图片描述

通过显示的程序窗口,可看到整个程序只做了很基本的 UI 窗口显示,但是代码结构也相对简单。如果需要实现更复杂的窗口界面呢?往下看。

使用 wxFormBuilder 设计复杂 UI

从上一节的 demo 代码中,看到要实现显示一个窗口是很简单的,但是如果窗口内部包含了很多其它部件呢?

继续手堆代码吗?不是不可以,但是这样子的做法对工程或者项目后期维护是很不利的。

那么怎么办?很巧,wxWidgets 框架提供了一个 GUI 构建器 wxFormBuilder。

在这里插入图片描述

打开 wxFormBuilder,可以看到提供了非常多的工具,而且自动创建一个空白工程。为了设计需要的界面,开发者可以通过手动点击组件面板(Component Palette)中不同种类的各种控件来布局界面,同时在编辑器(Editor)中生成设计图和各种开发语言的代码,支持 C++, Python, XRC, Lua 和 PHP 等。设计完成后,开发者只需要把对应页面的目标语言代码拷贝到自己的工程源文件中即可直接使用。

如需要安装 wxFormBuilder,建议前往官方下载页面获取对应平台安装包

https://github.com/wxFormBuilder/wxFormBuilder/releases

下面就使用 wxFormBuilder 来设计一个简单的界面。

一般界面都以 Frame 为底,所以在空白工程基础上添加一个 Frame 窗口。点击工作空间顶部的组件面板(Component Palette) -> Forms 类型 -> Frame 控件,如图

在这里插入图片描述

先在左边的控件树(Object Tree)面板里点击刚添加的 Frame 控件,然后在右边的对象属性(Object Properties)面板中就可以修改这个控件的属性了。这里修改控件的属性 name 为 w_frame_xrc,title 为 hello Python GUI APP!。最终输出代码会以一个窗口类的形式输出,而最底层窗口的 name 属性会决定这个窗口类的类名。

在这里插入图片描述

打算设计一个简单的名单录,为演示简单起见,只添加人员名称,而不编辑或者删除。按照元素控件的层次逐个添加,设计图最终效果图如下

在这里插入图片描述

如需要获取本工程所有源文件,包括设计文件等,可查看文末的链接。

设计界面完成后,点击编辑器(Editor)中的 Python 标签,复制窗口内所有内容,粘贴保存到新建的源文件 w_frame_xrc.py 中。

// w_frame_xrc.py

# -*- coding: utf-8 -*-

###########################################################################
## Python code generated with wxFormBuilder (version Oct 26 2018)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################

import wx
import wx.xrc

###########################################################################
## Class w_frame_xrc
###########################################################################

class w_frame_xrc ( wx.Frame ):

	def __init__( self, parent ):
		wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"hello Python GUI APP!", pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

		self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )

		bSizer1 = wx.BoxSizer( wx.VERTICAL )

		bSizer2 = wx.BoxSizer( wx.VERTICAL )

		sbSizer1 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"输入信息" ), wx.VERTICAL )

		bSizer3 = wx.BoxSizer( wx.HORIZONTAL )

		self.m_staticText_name = wx.StaticText( sbSizer1.GetStaticBox(), wx.ID_ANY, u"名字:", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText_name.Wrap( -1 )

		bSizer3.Add( self.m_staticText_name, 0, wx.ALL, 5 )

		self.m_textCtrl_name = wx.TextCtrl( sbSizer1.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		bSizer3.Add( self.m_textCtrl_name, 1, wx.ALL, 5 )


		sbSizer1.Add( bSizer3, 1, wx.EXPAND, 5 )


		bSizer2.Add( sbSizer1, 1, wx.EXPAND, 5 )

		bSizer4 = wx.BoxSizer( wx.VERTICAL )


		bSizer4.Add( ( 0, 0), 1, wx.EXPAND, 5 )

		self.m_button_add = wx.Button( self, wx.ID_ANY, u"添加", wx.DefaultPosition, wx.DefaultSize, 0 )
		bSizer4.Add( self.m_button_add, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )


		bSizer4.Add( ( 0, 0), 1, wx.EXPAND, 5 )


		bSizer2.Add( bSizer4, 1, wx.EXPAND, 5 )


		bSizer1.Add( bSizer2, 0, wx.EXPAND, 5 )

		self.m_staticText2 = wx.StaticText( self, wx.ID_ANY, u"列表:", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText2.Wrap( -1 )

		bSizer1.Add( self.m_staticText2, 0, wx.ALL, 5 )

		bSizer5 = wx.BoxSizer( wx.VERTICAL )

		self.m_listCtrl_info = wx.ListCtrl( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT )
		bSizer5.Add( self.m_listCtrl_info, 1, wx.ALL|wx.EXPAND, 5 )


		bSizer1.Add( bSizer5, 1, wx.EXPAND, 5 )


		self.SetSizer( bSizer1 )
		self.Layout()

		self.Centre( wx.BOTH )

	def __del__( self ):
		pass

为了使用 wxFormBuilder 构建器生成的代码,可以简单修改前面的代码,如下

// main.py

import wx
import w_frame_xrc

app = wx.App()
window = w_frame_xrc.w_frame_xrc(parent=None)
window.Show()
app.MainLoop()

执行程序

python main.py

在这里插入图片描述

现在界面看起来有点内容了!

实现逻辑

前面的界面还不具备任何的实际功能,为了让其执行设计的功能,添加额外的逻辑在所难免。

比如,点击按钮 添加,就触发动作把输入框中的名字添加到下方的列表中,并清空输入框,因此需要在原来的窗口类 w_frame_xrc.w_frame_xrc 基础上添加一些逻辑功能代码。

不过,wxFormBuilder 构建出来的代码一般不建议直接修改,所以先对原来的窗口类 w_frame_xrc.w_frame_xrc 进行派生,再在派生类中补充逻辑功能代码。派生类的代码存在单独的源文件 w_frame.py 中。

// w_frame.py

import wx
import w_frame_xrc

class w_frame(w_frame_xrc.w_frame_xrc):
    def __init__(self, parent):
        super(w_frame, self).__init__(parent)

        self.m_listCtrl_info.ClearAll()
        self.m_listCtrl_info.InsertColumn(0, u'名字', width=140)

        self.m_button_add.Bind(wx.EVT_BUTTON, self.on_button_add)

    def on_button_add(self, event):
        value = self.m_textCtrl_name.GetValue()
        if not value:
            print("You didn't enter anything!")
        else:
            self.m_listCtrl_info.InsertItem(self.m_listCtrl_info.GetItemCount(), value)
            self.m_textCtrl_name.Clear()

可以看到,当控件有特定的事件需要绑定连接到处理句柄时,可以通过 Bind() 方法,传入 EVT_xxx 事件类型和处理句柄(可调用对象,比如,函数等)。如果需要将已绑定的某个事件断开连接,可以将处理句柄位置参数设为 None 即可。

然后,main.py 也需要稍作修改,如下

// main.py

import wx
import w_frame

app = wx.App()
window = w_frame.w_frame(parent=None)
window.Show()
app.MainLoop()

好了,现在再来测试一下刚添加的逻辑,程序启动后往里添加几个名单看看吧。

python main.py

在这里插入图片描述

部署发布

目前来看,工程里都是一些以源码文件形式存在的脚本,但是在最终用户使用时,都是习惯于直接双击一个 exe 文件来启动软件进程。

下面就介绍一种对 Python 脚本工程打包的工具,目标是最终输出一个可执行的 exe 文件。

这个工具就是 pyinstaller,使用之前需要确认一下自己的环境里是否已经安装有这个第三方包,还用指令 pip list 即可查看。

如果确认过没有,那么用下面的指令可以安装

pip install pyinstaller

假设已经安装完毕,直接打包。选项 -F 后边输入启动脚本文件

pyinstaller -F main.py

启动打包过程之后,工程目录下面会自动生成一个新目录 dist 用于存放输出的目标文件。由于上面的打包指令没有指明输出的目标文件名,所以默认输出为脚本文件同名,如 main.exe。

如果需要指明输出的目标文件名,可以加上选项 -n。比如要输出目标为 demo.exe,可以这样

pyinstaller -F main.py -n demo

也许有的同学喜欢让打包的输出文件带上图标,那么可以加上选项 -i。比如工程目录里有一份图标文件 logo.ico,需要让打包后输出文件带上这个图标,可以这样

pyinstaller -F main.py -n demo -i logo.ico

打包完毕,双击程序 demo.exe,可能会发现在运行起来的软件背景里,老是有个命令行的窗口,这样子真的很碍眼!

怎样把终端窗口给隐藏掉呢?打包的时候带上选项 -w,这样

pyinstaller -F main.py -n demo -i logo.ico -w

网上有些同学喜欢吐槽 pyinstaller 打包出来的目标文件体积过大,关于这个问题的解决思路是,工程开发(包括目标文件打包输出)应该在配置好的单独虚拟环境下进行,环境中不应该安装任何不需要的第三方包!

全文到这里算是结束了,欢迎你的留言!

​工程代码仓库:​git@github.com:ifi-leung/python_gui_wx.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1357466.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

极速 JavaScript 打包器:esbuild

文章目录 引言什么是esbuild?esbuild的特点esbuild如何实现如此出色的性能?esbuild缺点基本配置入口文件输出文件模块格式targetplatformexternalbanner和footer 高级配置插件系统自定义插件压缩代码调试代码 结论😶 写在结尾 引言 esbuild是…

leetcode:724. 寻找数组的中心下标

一、题目 二、函数原型 int pivotIndex(int* nums, int numsSize) 三、思路 首先要理解正确中心下标,中心下标左侧元素之和等于右侧元素之和,比较时是不包含中心下标所指元素的。 先将数组和求出来记为sum,再遍历数组,遍历到…

快速批量运行命令

Ansible 是 redhat 提供的自动化运维工具,它是 Python编写,可以通过 pip 安装。 pip install ansible 它通过任务(task)、角色(role)、剧本(playbook) 组织工作项目,适用于批量化系统配置、软件部署等需要复杂操作的工作。 但对于批量运行命…

pytorch集智-1安装与简单使用

1 安装 1.1 简介 pytorch可用gpu加速,也可以不加速。gpu加速是通过cuda来实现,cuda是nvidia推出的一款运算平台,它可以利用gpu提升运算性能。 所以如果要装带加速的pytorch,需要先装cuda,再装pytorch,如…

【重点】【BFS】542.01矩阵

题目 法1&#xff1a;经典BFS 下图中就展示了我们方法&#xff1a; class Solution {public int[][] updateMatrix(int[][] mat) {int m mat.length, n mat[0].length;int[][] dist new int[m][n];boolean[][] used new boolean[m][n];Queue<int[]> queue new Li…

excel中解决多行文本自动调整行高后打印预览还是显示不全情况

注意&#xff1a;此方法对于多行合并后单元格行高调整不适用&#xff0c;需要手动调整&#xff0c;如大家有简便方法&#xff0c;欢迎评论。 一、调整表格为自动调整行高 1&#xff09;点击此处全选表格 2&#xff09;在第一行序号单元格的下端&#xff0c;鼠标成黑十字时&am…

【React系列】父子组件通信—props属性传值

本文来自#React系列教程&#xff1a;https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. 认识组件的嵌套 组件之间存在嵌套关系&#xff1a; 在之前的案例中&#xff0c;我们只是创建了一个组件App&…

机器人制作开源方案 | 清洁机器人

作者&#xff1a;胡志宇、白永康、颉志国、刘昭迅、王维浩 单位&#xff1a;北京石油化工学院 指导老师&#xff1a;陈亚、王殿军 1. 设计方案论证 1.1 清洁机器人方案选择 目前&#xff0c;市场上清洁机器人比比皆是&#xff0c;各大品牌之间的竞争也相当激烈&#xff0c;…

docker kafka go demo

配置 创建网桥 docker network create app-tier --driver bridge拉取并启动镜像 docker run -d --name kafka-server --hostname kafka-server \--network app-tier \-p 9092:9092 \-e ALLOW_PLAINTEXT_LISTENERyes \-e KAFKA_CFG_ADVERTISED_LISTENERSPLAINTEXT://192.168.…

链表--206. 反转链表/easy

206. 反转链表 1、题目2、题目分析3、解题步骤4、复杂度最优解代码示例5、抽象与扩展 1、题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2…

【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行环境搭建

【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 概述-CSDN博客 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行环境搭建-CSDN博客 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行模式-CSDN博客 1、模板虚拟机环境准备 1.1、 hadoop100 虚拟机配置要求如下 &…

如何通过Python将各种数据写入到Excel工作表

在数据处理和报告生成等工作中&#xff0c;Excel表格是一种常见且广泛使用的工具。然而&#xff0c;手动将大量数据输入到Excel表格中既费时又容易出错。为了提高效率并减少错误&#xff0c;使用Python编程语言来自动化数据写入Excel表格是一个明智的选择。Python作为一种简单易…

【Spring进阶系列丨第六篇】Spring的Bean管理(基于注解)

文章目录 一、说明二、用于创建对象的2.1、Component注解2.1.1、定义Bean2.1.2、主配置文件配置扫描注解2.1.3、测试2.1.4、Component注解总结 2.2、Controller注解2.3、Service注解2.4、Repository注解 三、用于注入数据的3.1、Autowired注解3.1.1、定义Bean3.1.2、主配置文件…

《PCI Express体系结构导读》随记 —— 第I篇 第2章 PCI总线的桥与配置(6)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第I篇 第2章 PCI总线的桥与配置&#xff08;5&#xff09; 2.2 HOST主桥 本节以MPC8548处理器为例&#xff0c;说明HOST主桥在PowerPC处理器中的实现机制&#xff0c;并简要介绍x86处理器系统使用的HOST主桥。 …

【springboot+vue项目(零)】开发项目经验积累(处理问题)

一、VUEElement UI &#xff08;一&#xff09;elementui下拉框默认值不是对应中文问题 v-model绑定的值必须是字符串&#xff0c;才会显示默认选中对应中文&#xff0c;如果是数字&#xff0c;则显示数字&#xff0c;修改为&#xff1a; handleOpenAddDialog() {this.dialogT…

【Emgu.CV教程】第24篇 、色彩处理之LUT()查找表转换颜色

LUT (Look-Up Table)查找表转换&#xff0c;是对原始图像的像素数值进行快速转换&#xff0c;以实现图像的像素压缩目的。LUT()函数的官方定义如下&#xff1a; public static void LUT(IInputArray src, // 输入图像IInputArray lut, // 查找表IOutputArray dst, // 输出图像…

2023春季李宏毅机器学习笔记 05 :机器如何生成图像

资料 课程主页&#xff1a;https://speech.ee.ntu.edu.tw/~hylee/ml/2023-spring.phpGithub&#xff1a;https://github.com/Fafa-DL/Lhy_Machine_LearningB站课程&#xff1a;https://space.bilibili.com/253734135/channel/collectiondetail?sid2014800 一、图像生成常见模型…

提示循环引用 一个循环引用但无法列出导致循环的引用且文件打不开无法修改

目录 设备环境&#xff1a; 提示内容&#xff1a; 具体错误问题描述&#xff1a; 图示&#xff1a; Office 报错 WPS 报错 问题分析&#xff1a; 问题解决&#xff1a; 关注我的 GitHub&#xff08;魔法网络访问&#xff09;&#xff1a; 设备环境&#xff1a; Window…

(湖科大教书匠)计算机网络微课堂(下)

第四章、网络层 网络层概述 网络层主要任务是实习网络互连&#xff0c;进而实现数据包在各网络之间的传输 因特网使用TCP/IP协议栈 由于TCP/IP协议栈的网络层使用网际协议IP&#xff0c;是整个协议栈的核心协议&#xff0c;因此TCP/IP协议栈的网络层常称为网际层 网络层提供…