python桌面开发,为啥选择PyQt或wxPython,而不使用Tkinter?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python桌面开发,为啥选择PyQt或wxPython,而不使用Tkinter?相关的知识,希望对你有一定的参考价值。
最主要的原因就是Tkinter参考资料太少,只能满足基本GUI开发(界面美观程度要求不高),因此使用的人比较少,而PyQt和wxPython参考资料丰富,可以直接拖拽控件,界面设计美化容易,因此使用的人比较多,下面我简单介绍一下这2个模块的安装和使用,感兴趣的朋友可以自己尝试一下:wxPython
这是Python一个非常不错的GUI开发库,免费、开源、跨平台,可用组件众多,借助这些组件,程序员可以快速创建完整、功能全面的用户界面,因此应用非常广泛,下面我简单介绍一下这个库:
1.首先,安装wxPython,这个直接在cmd窗口输入安装命令“pip install wxpython”就行,如下,我的Python环境已正确安装:
2.安装完成后,我们就可以直接编写代码来测试这个模块了,代码如下,非常简单,一个文本编辑器,根据路径打开文件,然后编辑再保存:
程序运行截图如下,效果还是非常不错的:
PyQt
这是一个基于Qt的Python接口包,借助于Qt强大的可视化功能,Python也可以快速开发一个功能强大、界面美观的GUI程序(可以直接拖拽控件),下面我简单介绍一下这个库:
1.首先,安装PyQt,这个也直接在cmd窗口输入命令“pip install pyqt5”就行,如下,安装的过程需要耐心等待一会儿:
2.安装完成后,我们就可以直接打开Qt自带的设计工具Qt Designer进行界面设计了,默认在site-packages->PyQt5->Qt->bin目录下,所有控件都可以直接拖拽,而且可以使用QSS进行美化,非常方便,如下:
3.设计完成后,使用pyuic5工具进行转化,就会自动生成对应Python代码,如下,不需要我们再手动去一行一行编写,调整布局:
4.最后再加一个main函数,创建上面的类对象,就可以显示我们创建的界面了,如下:
运行程序,截图如下,就是我们刚才设计的GUI界面,非常方便吧,再绑定信号和槽函数,就可以进行用户响应啦:
至此,我们就介绍完了PyQt和wxPython这2个模块的简单安装和使用。总的来说,对于界面简单、功能要求不高的GUI设计来说,Tkinter完全可以胜任,但是对于功能比较复杂、界面美化程度较高的GUI来说,PyQT和wxPython更容易,也更好实现,网上也有相关教程和资料,介绍的非常详细,感兴趣的话,可以搜一下,希望以上分享的内容能对你有所帮助吧,也欢迎大家评论、留言进行补充。 参考技术A tkinter需要自己编程写页面,而且界面没美观程度不高,pyqt直接拖控件设计,比较方便。
桌面太单调?一起用Python做个自定义动画挂件,好玩又有趣!
前言
前段时间,写了篇博客关于Python自制一款炫酷音乐播放器。有粉丝问我,音乐播放器为什么要用PyQt5,效果是不是比Tkinter赞?PyQt5真的可以实现这些炫酷的UI画面吗?之前没接触过PyQt5,能不能多分享一些这方面的开发案例?
今天就带大家,一起用Python的PyQt5开发一个有趣的自定义桌面动画挂件,看看实现的动画挂件效果!
下面,我们开始介绍这个自定义桌面动画挂件的制作过程。
一、核心功能设计
总体来说,我们需要实现将自己喜欢的动态图gif或者视频转成一个桌面动画挂件,知识点主要包含了对GIF图/视频解析,人像提取分割,PyQt5窗体设置,自定义挂件动画实现,ico图标生成,程序打包等。
拆解需求,大致可以整理出我们需要分为以下几步完成:
- 对gif或者视频进行逐帧解析,获取转换的图片,提取图像中人体区域,并对图片进行批量尺寸大小修改替换
- 初始化设置动画挂件窗体显示效果,窗体位置、大小等
- 桌面动画挂件功能实现,动画轮播、鼠标控制挂件位置拖动
- 挂件打包图标设置、打包配置
二、实现步骤
1. 解析提取,修改图片
GIF图解析:
Gif动态图资源大家可以根据自己的喜好,自己选择。博主就用之前写过的仙女蹦迪动态Gif来演示效果。
首先我们需要将Gif动态图按照每一帧进行解析 ,转换成图片格式。代码如下:
from PIL import Image # 导入PIL的Image包
import os
gifFileName = "./demo.gif" # 把gif图赋值给gifFileName
im = Image.open(gifFileName) # 使用Image的open函数打开test.gif图像
pngDir = gifFileName[:-4] # 倒着从gifFileName中的倒数第四个开始取字符(跳过.gif),赋值给pngDir,作为文件夹的名字
if not os.path.exists(pngDir):
os.makedirs('./img') # 用图片名创建一个文件夹,用来存放每帧图片,名字为pngDir的值
try:
while True: # 死循环
current = im.tell() # 用tell函数保存当前帧图片,赋值给current
im.save(pngDir+'/'+str(current+1)+'.png') # 调用save函数保存该帧图片
im.seek(current+1) # 调用seek函数获取下一帧图片,参数变为current帧图片+1
# 这里再次进入循环,当为最后一帧图片时,seek会抛出异常,代码执行except
except EOFError:
pass # 最后一帧时,seek抛出异常,进入这里,pass跳过
这样就可以把动态Gif图转换成图片了,效果如下:
视频解析:
同理,对视频解析,也是按照每一帧进行解析,转换成图片格式。核心代码如下:
# 将视频按照每一帧转成图片png
import cv2
videoFileName = "./demo.mp4" # 把视频路径赋值给videoFileName
pngDir = videoFileName[:-4] # 倒着从gifFileName中的倒数第四个开始取字符(跳过.后缀),赋值给pngDir,作为文件夹的名字
if not os.path.exists(pngDir):
os.makedirs(pngDir) # 用图片名创建一个文件夹,用来存放每帧图片,名字为pngDir的值
# 视频处理 分割成一帧帧图片
cap = cv2.VideoCapture(videoFileName)
num = 1
while True:
# 逐帧读取视频 按顺序保存到本地文件夹
ret, frame = cap.read()
if ret:
cv2.imwrite(f"{pngDir}/{num}.png", frame) # 保存一帧帧的图片
num += 1
else:
break
cap.release() # 释放资源
效果如下:
逐帧提取的图片已经拿到了,下面我们需要对这些图片中的人像进行分割提取。
人像分割:
我们调用的是百度开放的人体分析接口 – 百度AI开放平台链接。
这里面我们可以创建一个人像分割的应用,其中的API Key及Secret Key后面我们调用人脸识别检测接口时会用到。
我们可以看到官方提供的帮助文档,介绍地很详细。如何调用请求URL数据格式,向API服务地址使用POST发送请求,必须在URL中带上参数access_token,可通过后台的API Key和Secret Key生成。这里面的API Key和Secret Key就是我们上面提到的。
那我们如何获取空背景的人像图片呢?根据API文档,可以看到里面有个type属性设置为foreground 就可以提取空背景的人像图片。
人像分割的接口流程基本就已经清楚了,可以进行代码实现了。
# 保存图片
def save_base_image(img_str, filename):
img_data = base64.b64decode(img_str)
with open(filename, 'wb') as f:
f.write(img_data)
# 获取token
def get_token():
host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + client_id + '&client_secret=' + client_secret
request = urllib.request.Request(host)
request.add_header('Content-Type', 'application/json; charset=UTF-8')
response = urllib.request.urlopen(request)
token_content = response.read()
if token_content:
token_info = json.loads(token_content)
token_key = token_info['access_token']
return token_key
# 人像分割
def body_seg_fore(filename, resultfilename):
request_url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_seg"
# 二进制方式打开图片文件
f = open(filename, 'rb')
img = base64.b64encode(f.read())
params = dict()
params['image'] = img
params['type'] = 'foreground'
params = urllib.parse.urlencode(params).encode("utf-8")
# params = json.dumps(params).encode('utf-8')
access_token = get_token()
request_url = request_url + "?access_token=" + access_token
request = urllib.request.Request(url=request_url, data=params)
request.add_header('Content-Type', 'application/x-www-form-urlencoded')
response = urllib.request.urlopen(request)
content = response.read()
if content:
# print(content)
content = content.decode('utf-8')
# print(content)
data = json.loads(content)
# print(data)
img_str = data['foreground']
save_base_image(img_str, resultfilename)
这样我们就可以根据图片,进行人像分割,提取出空背景的人像图。效果如下:
如果提取的人像图片大小不符合我们的要求,我们还可以对图片大小进行调整。
file_list = os.listdir("./image") # 读取当前文件夹所有文件
# print(file_list)
n = len(file_list)
for i in range(n):
s = str(file_list[i])
if s[-4:] == ".png": # 检查后缀
src = os.path.join(os.path.abspath('./image/'), s) # 原先的图片名字
img = Image.open(src)
new_img = img.resize((128, 128), Image.BILINEAR)
new_img.save(src)
我们需要的空背景图片已经拿到了,接下来我们来实现桌面挂件功能。
2. 初始化动画挂件
# 窗体初始化
def windowinit(self):
self.x = 1650
self.y = 860
self.setGeometry(self.x, self.y, 300, 300)
self.setWindowTitle('My Gadgets')
self.img_num = 1
self.img_path = './image/{file}/{img}.png'.format(file=self.dis_file, img=str(self.img_num))
self.lab = QLabel(self)
self.qpixmap = QPixmap(self.img_path)
self.lab.setPixmap(self.qpixmap)
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
self.setAutoFillBackground(False)
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.show()
def __init__(self):
super(Gadgets, self).__init__()
self.dis_file = "img1"
self.windowinit()
self.icon_quit()
self.pos_first = self.pos()
self.img_count = len(os.listdir('./image/{}'.format(self.dis_file)))
这样图片挂件就可以显示出来,效果如下:
现在的桌面挂件是静态显示,下面我们可以通过计时器进行挂件动画轮播显示。
3. 动画挂件功能实现
动画轮播:
self.timer = QTimer()
self.timer.timeout.connect(self.img_update)
self.timer.start(100)
def img_update(self):
if self.img_num < self.img_count:
self.img_num += 1
else:
self.img_num = 1
self.img_path = './image/{file}/{img}.png'.format(file=self.dis_file, img=str(self.img_num))
self.qpixmap = QPixmap(self.img_path)
self.lab.setPixmap(self.qpixmap)
鼠标控制挂件位置拖动:
def mousePressEvent(self, QMouseEvent):
if QMouseEvent.button() == Qt.LeftButton:
self.pos_first = QMouseEvent.globalPos() - self.pos()
QMouseEvent.accept()
self.setCursor(QCursor(Qt.OpenHandCursor))
def mouseMoveEvent(self, QMouseEvent):
if Qt.LeftButton:
self.move(QMouseEvent.globalPos() - self.pos_first)
print(self.pos())
self.x, self.y = self.pos().x, self.pos().y
QMouseEvent.accept()
def quit(self):
self.close()
sys.exit()
至此,自定义动画挂件功能已经实现完成,动画挂件效果如下:
4. 打包配置
前段时间有粉丝问我,Python能不能打包成exe?如何打包呢?今天就通过这个来一起介绍下。
Python常用的打包工具是第三方库Pyinstaller,首先需要安装下pyinstaller。
pip install Pyinstaller
接下来,我们需要打开命令窗口,切换到项目目录下再执行打包命令。
pyinstaller -F -i ./img.ico Qt_Gadgets.py
打包常用的参数如下:
-
-F 表示生成单个可执行文件
-
-w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!
-
-p 表示你自己自定义需要加载的类路径,一般情况下用不到
-
-i 表示可执行文件的图标
之前有小伙伴问我,打包的图标需要.ico后缀的图片,应该如何把普通图片转成图标格式.ico呢?Python当然可以帮你实现,今天就一起教给大家。核心代码如下:
import PythonMagick
# 生成图标ico(png格式图片转成ico)
img = PythonMagick.Image('./image/img1/1.png')
# 这里要设置一下尺寸,不然会报ico尺寸异常错误
img.sample('128x128')
img.write('./img.ico')
图标得到了,下面我们就可以进行打包操作了。
打包完成之后,我们可以看见项目目录下会有生成的exe程序。
至此,整个自定义动画挂件就全部完成了,下面我们一起运行下exe看看动画挂件效果。
今天我们就到这里,明天继续努力!
若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。
创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
Dragon少年 | 文
如果本篇博客有任何错误,请批评指教,不胜感激 !
以上是关于python桌面开发,为啥选择PyQt或wxPython,而不使用Tkinter?的主要内容,如果未能解决你的问题,请参考以下文章
桌面太单调?一起用Python做个自定义动画挂件,好玩又有趣!