Python PySide2小程序和打包
工作环境:Python3.6 PySide2 PyInstaller
工作时间:2019/03/18-2019/03/23
之前已经做了几个小插件,可以实现一些图像处理的功能。但是我认为这样是不完整的。从我大三学C++的时候开始,我就希望自己能够写出一个正式的windows可执行的软件。既要有UI,又要可以脱离Python的环境在任何一个机器上执行。以前我一直用MATLAB做了很多科学计算和分析,但是MATLAB不太支持脱离MALAB环境工作。
Python提供了这种可能!
可以用PySide2做一个图形化的交互界面,然后使用PyInstaller。
文章目录
1.处理思路
- 设计好UI,按功能和布局用代码实现;
- 将各个功能脚本和该UI脚本对接;
- 使用PyInstaller打包文件,生成可执行文件。
2.关于PySide2
- 布局方法
先说一下PySide2中非常重要的一个概念,就是BoxLayout。通常,UI里的一个文本框,一个图片,一个按钮等等,都叫Widget。而这些Widget我都用GroupBox的方法去将他们整合成一排,一列或者一个grid等。举个栗子,如下图所示,
这个图中,有两个Widget,都是QLable,一个内容是图片,一个内容是文字。周围有一个小框框,表示这两个Widget被装在了一个GroupBox中。其代码如下:# 首先实例化这个Box,命名为self.creator self.creator = QtWidgets.QGroupBox() # 分别实例化两个QLabel self.imageradi = QtWidgets.QLabel(self, pixmap=QPixmap("image\\radi.jpg")) self.date = QtWidgets.QLabel('2019年3月21日') # 设置文字的格式 self.date.setFont(QFont("Roman times",12,QFont.Bold)) # 实例化布局格式,V表示衡行,H表示竖行 layout = QVBoxLayout() # 将先前实例化的QLabel加入这个布局中 layout.addWidget(self.imageradi) layout.addWidget(self.date) # 将布局加入到creator这个box里 self.creator.setLayout(layout)
- 触发动作方法
当我点击了一个按钮之后,它是如何进行工作的?先看一下下面一行代码:
self.connect(self.FindFile, QtCore.SIGNAL('clicked()'), self, QtCore.SLOT('openFileDialog()'))
其中,self.FindFile是我之前定义的一个QPushButton(按钮)。QtCore.SLOT是一种方法,openFileDialog()则是我定义的另一个方法。这句话的意思大概可以翻译为:当self.FindFile收到clicked()信号之后,通过QtCore.SLOT执行self.openFileDialog()。这样,当我们点击这个按钮时,就会开始执行相应的方法内的任务。
3.代码结构
3.1.import
这里除了调用Pyside2的库,还需要调用以下之前写好的脚本,做好接口也是一个重要工作!
import...
# 读取图片信息脚本
from info_img import info_img
# 图片转换脚本
from grey2rgb import grey2rgb
# 图片切割脚本
from cut_img import cut_img
3.2.class Form下的__init__方法
这个方法定义了UI的主窗口,让我们看看都有什么内容:
class Form(QMainWindow):...
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.init_ui()
self.Widget = QWidget()
self.createSettingBox()
self.createColorBox()
self.createInfoBox()
self.mainLayout = QVBoxLayout()
self.mainLayout.addWidget(self.createSettingBox)
self.mainLayout.addWidget(self.createColorBox)
self.mainLayout.addWidget(self.createInfoBox)
self.Widget.setLayout(self.mainLayout).
# 这一行是特有的
self.setCentralWidget(self.Widget)
实际上,__init__里,我定义了最外层的一Widget,只不过这些Widget都在下面以方法的形式定义,并且他们本身都是一些box。
3.3.其他方法
除了主窗口,我们还分别定义了几个被主窗口调用的小窗口和一些被触发的方法。被连接和触发执行的方法跟在@QtCore.Slot()之后。
def createSettingBox(self):...
def createColorBox(self):...
def createInfoBox(self):...
@QtCore.Slot()
def openFileDialog(self):...
@QtCore.Slot()
def choseFileDialog(self):...
@QtCore.Slot()
def showinfo(self, inputpath):...
@QtCore.Slot()
def outputfile(self, outputpath):...
def init_ui(self):...
def openMessageBox(self,context):...
def init_ui(self)定义了主窗口的一些参数,而def openMessageBox(self,context)则是我定义的一个弹出的新窗口。因为会经常用到,我就干脆直接定义了一个方法。
最后的效果如下图所示:
3.4.import内容
import sys
import os
# 读取图片信息脚本
from info_img import info_img
# 图片转换脚本
from grey2rgb import grey2rgb
# 图片切割脚本
from cut_img import cut_img
from PySide2.QtWidgets import (QMainWindow, QPushButton, QApplication, QVBoxLayout, QFileDialog, QLabel, QHBoxLayout, QWidget)
from PySide2.QtCore import Qt
from PySide2.QtGui import QPixmap,QFont
from matplotlib.backends.qt_compat import QtCore, QtWidgets
import的内容特别乱(竟然还有matplotlib!)有些部分我也是借鉴的别人的代码。实际上我也可以优化一下不用这个库。也能运行,但是之后打包的时候就会无法打开生成的exe文件。
4.PyInstaller
我用PyInstaller这个功能,直接在所在文件夹打开console键入:
pyinstaller -F main.py
-F表示生成一个独立的可执行的exe文件。-m表示生成的文件不带cmd
我试了一下,对我来说只有这样生成的文件才能打开。去网上sou了一下问题,说就是自己代码的问题。可能存在一些问题,python可以包容,但是pyinstaller不能包容。我也懒得改了。以后写代码之前还是规范规范比较好。
需要注意的是,所有的路径最好设置成相对路径?比如我读取了几个图片,及时我生成了一个独立可执行的exe文件,如果没有把这几个图片放对应的相对位置就会无法显示。我不清楚如果是绝对路径会怎么样。
5.写在最后
前前后后2周左右时间写这个小插件,从底层的代码到后面的打包。各个库也是一边做一边上网查用法一边写。虽然做的很垃圾也很基础,但是毕竟是自己第一个做的小项目。还是有点开心和成就感的。之前做Hadoop环境搭建,一周可能啥进展都没有,很有挫败感。感觉还是写脚本舒服呀!
但是现在想想,还是有以下的问题:
- 正常的项目是不是用这种class+def的方法,然后通过import调用方法的途径实现项目的整合的?
- 代码书写的格式,包括实例化命名的方法和一些书写规范并没有在我的代码里面体现出来。
说到底,我觉得用python写前端还是个体力活。。。
6.附录
为了便于查找和理解,整理了一些常用的方法:
设置大小:setFixedHeight(20)和setFixedWidth(20)
设置标题(Box):setTitle
方形的执行按钮:
实例化:QPushButton
选型的选择按钮:
实例化:QRadioButton()
状态确认:isChecked()
状态设置:setChecked(True)
label:
实例化:Qlabel()
加图片:Qlabel(self, pixmap=QPixmap(“image\1r.png”))
* * 注:加图片需要 from PySide2.QtGui import QPixmap,QFont*
修改文字:setText()
增加文字:append()
读取信息:text()
QTextEdit
修改文字:setText()
增加文字:append()
读取信息:toPlainText
注:所有的文字信息读取都是str型。