从安装到查资料(Debug)到做成软件,用了不到一天。做出第一个自己的exe还是非常有有成就感。
因为学pyqt5目的是做图像有关的展示,所以先做一个玩具吧。
学习目录
安装:pyqt5安装及基础使用教程
Windows环境安装PyQt5以及安装过程出现问题时的解决方案
这个网址上下载最新版本:
https://pypi.tuna.tsinghua.edu.cn/simple/pyqt5-tools/
速成视频教学:【简单易懂GUI教程】使用pyqt5+QtDesigner快速制作多功能GUI并打包成exe
Pyqt5官方文档的中文翻译版:https://maicss.gitbook.io/pyqt5-chinese-tutoral/
一个Demo的制作
1.用Designer直接画图
Designer可以直接搜软件,也可以配置后从PyCharm里面打开,配置方法上面的安装里面有。我选择用Pycharm。
就简单画图设置字体啥的,其它函数功能就代码实现。初步界面是这样的。
就是很简单的一个界面,打算用代码必须实现的是:
- 一个输入框(地址,可以拖入显示)
- 两个功能按键(函数)
- 一个响应框(Label)
- 一个背景
其它的调整可有可无
保存这个.ui文件后,在Pycharm转为对应的.py文件。如果直接修改ui还要重新转码,会覆盖之前的.py文件。【这不是很方便!两个都可以修改,哪个方便用哪个!最后封装的应该是.py】我就在这样一直调整。
2.编辑.py实现函数功能
这个直接由ui生成的文件,大家都是成熟程序员了,函数没见过,猜也能猜得到这些是什么意思,设置了一些对象的属性。
这个文件是没有main只有类的,所以运行不会弹出界面!要写个main函数。
怕自己把直接生成的文件改糊了,于是我们直接新建一个call_XX.py增加功能。当然可以在这里直接继续写。这样子单独列也方便我们在ui改了界面之后重新生成py,不影响函数配置。
call_trans.py
# sys模块提供了许多函数和变量来处理 Python 运行时环境的不同部分
import sys
#PyQt5中使用的基本控件都在PyQt5.QtWidgets模块中
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtGui import QPixmap, QPalette, QBrush
# 这个是直接生成文件里面的类窗口类(需要继承补充功能的)
from trans import Ui_MainWindow
class MyMainForm(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MyMainForm, self).__init__(parent)
self.setupUi(self)
# 前面基本是不用管,除了名字是自己命名的
# 写在这里等同于直接写在
# class Ui_MainWindow(object):
# def setupUi(self, MainWindow):
# 根据前面的中文信息和其他提示,也能判断出来自己的对象是啥名字
# 添加按钮信号和槽。表示按这个按键就调用函数后面的函数,注意不加小括号()
# 函数自己命名实现,当然可也以选择已经有的函数,比如close(关闭程序)
# 对应“导入图片”
self.pushButton.clicked.connect(self.importimg)
# 对应“清除”[clear这个就是一个系统设置好的清除内容函数了,清除了我的地址输入框]
self.pushButton_2.clicked.connect(self.textEdit.clear)
# 识别控件内容,实现拖拽自动获取路径,控件已经将acceptDrops设置为True
self.textEdit.textChanged.connect(self.editchange)
# 设置背景
palette = QPalette()
pix = QPixmap("backpictures/5.jpg")
pix = pix.scaled(self.width(), self.height())
palette.setBrush(QPalette.Background, QBrush(QPixmap(pix)))
self.setPalette(palette)
# 写在这里相当于写在
# class Ui_MainWindow(object):
# 实现上面自定义的按钮函数
def importimg(self):
# 获取界面上地址输入框的内容
img_path = self.textEdit.toPlainText()
pixmap = QPixmap(img_path)
self.label_2.setPixmap(pixmap)
self.label_2.setScaledContents(True) # 让图片适应窗口大小
# 去掉多于地址的头
def editchange(self):
if 0 == self.textEdit.toPlainText().find('file:///'):
self.textEdit.setText(self.textEdit.toPlainText().replace('file:///', ''))
if __name__ == "__main__":
# 固定的,PyQt5程序都需要QApplication对象。
# sys.argv是命令行参数列表,确保程序可以双击运行
app = QApplication(sys.argv)
# 初始化
myWin = MyMainForm()
# 将窗口控件显示在屏幕上
myWin.show()
# 程序运行,sys.exit方法确保程序完整退出。
sys.exit(app.exec_())
trans.py
就是由trans.ui直接转换的。等我以后学好了!连这个界面我都自己码!
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'trans.ui'
#
# Created by: PyQt5 UI code generator 5.14.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(987, 685)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.line = QtWidgets.QFrame(self.centralwidget)
self.line.setGeometry(QtCore.QRect(60, 170, 791, 20))
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.splitter = QtWidgets.QSplitter(self.centralwidget)
self.splitter.setGeometry(QtCore.QRect(250, 130, 441, 37))
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.splitter_2 = QtWidgets.QSplitter(self.splitter)
self.splitter_2.setOrientation(QtCore.Qt.Horizontal)
self.splitter_2.setObjectName("splitter_2")
self.pushButton = QtWidgets.QPushButton(self.splitter_2)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0, 128))
brush.setStyle(QtCore.Qt.NoBrush)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.PlaceholderText, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0, 128))
brush.setStyle(QtCore.Qt.NoBrush)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.PlaceholderText, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(225, 237, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
brush = QtGui.QBrush(QtGui.QColor(170, 0, 0, 128))
brush.setStyle(QtCore.Qt.NoBrush)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush)
self.pushButton.setPalette(palette)
self.pushButton.setStyleSheet("color: rgb(170, 0, 0);\n"
"background-color: rgb(225, 237, 255);\n"
"font: 14pt \"Agency FB\";")
self.pushButton.setCheckable(False)
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.splitter_2)
self.pushButton_2.setStyleSheet("color:rgb(170, 0, 0);font: 14pt \"Agency FB\";\n"
"background-color: rgb(225, 237, 255);")
self.pushButton_2.setObjectName("pushButton_2")
self.splitter_4 = QtWidgets.QSplitter(self.centralwidget)
self.splitter_4.setGeometry(QtCore.QRect(90, 80, 701, 41))
self.splitter_4.setOrientation(QtCore.Qt.Horizontal)
self.splitter_4.setObjectName("splitter_4")
self.label_4 = QtWidgets.QLabel(self.splitter_4)
self.label_4.setObjectName("label_4")
self.textEdit = QtWidgets.QTextEdit(self.splitter_4)
self.textEdit.setObjectName("textEdit")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(130, 220, 721, 351))
self.label_2.setStyleSheet("background-color: rgb(231, 255, 249);")
self.label_2.setText("")
self.label_2.setObjectName("label_2")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 987, 27))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.pushButton_2.clicked.connect(self.textEdit.clear)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "图像读取"))
self.pushButton.setText(_translate("MainWindow", "导入图片"))
self.pushButton_2.setText(_translate("MainWindow", "清除"))
self.label_4.setText(_translate("MainWindow", "<html><head/><body><p align=\"center\"><span style=\" font-size:14pt; font-weight:600; color:#00557f;\">图片地址:</span></p></body></html>"))
self.textEdit.setToolTip(_translate("MainWindow", "<html><head/><body><p align=\"center\">在这里输入绝对地址(可以使用拖拽文件至对话框)</p></body></html>"))
界面展示
直接运行call_tans.py后效果
3.封装成exe
1.随意挑选一个jpg等图片转换成ico图标,放在.py文件目录下。
用百度搜的在线转换都行。随便挑的一个在线生成透明ICO图标
2.安装一个pyinstaller库(pip)
3.在文件目录下执行pyinstaller -F -w (py文件名)
-F 表示生成单个可执行文件;
-D –onedir 创建一个目录,包含exe文件,但会依赖很多文件(默认选项)。
-w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!;
-c –console, –nowindowed 使用控制台,无界面(默认);
-p 表示你自己自定义需要加载的类路径,一般情况下用不到;
-i 表示可执行文件的图标。
这个打包背景的问题我还没解决,不过目前教程都是这样的:
Pyinstaller 使用+打包图片方法
在打包后序工程时,打包成功,但是不能运行