• 花一上午帮同学写的期末作业
  • 大概写下流程记录下

Begin

GUI设计

使用Qt Designer完成 .ui文件
生成py文件 pyuic5 -o xx.py xx.ui

代码

管理端

from PyQt5 import QtCore, QtGui, QtSql, QtWidgets
import sys
import sqlite3
import os
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel
from PyQt5.QtWidgets import QApplication, QWidget

# 管理界面GUI


class manageUI(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1000, 400)
        Form.setFixedSize(Form.width(), Form.height())
        self.tableView = QtWidgets.QTableView(Form)
        self.tableView.setGeometry(QtCore.QRect(10, 10, 981, 291))
        self.tableView.setObjectName("tableView")
        self.gridLayoutWidget = QtWidgets.QWidget(Form)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 310, 481, 80))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.pushButton = QtWidgets.QPushButton(self.gridLayoutWidget)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
        self.pushButton_2 = QtWidgets.QPushButton(self.gridLayoutWidget)
        self.pushButton_2.setObjectName("pushButton_2")
        self.gridLayout.addWidget(self.pushButton_2, 1, 0, 1, 1)
        self.gridLayoutWidget_2 = QtWidgets.QWidget(Form)
        self.gridLayoutWidget_2.setGeometry(QtCore.QRect(510, 310, 481, 80))
        self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget_2)
        self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.gridLayoutWidget_2)
        self.pushButton_3.setObjectName("pushButton_3")
        self.gridLayout_2.addWidget(self.pushButton_3, 0, 0, 1, 1)
        self.pushButton_4 = QtWidgets.QPushButton(self.gridLayoutWidget_2)
        self.pushButton_4.setObjectName("pushButton_4")
        self.gridLayout_2.addWidget(self.pushButton_4, 1, 0, 1, 1)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "隔离人员管理"))
        self.pushButton.setText(_translate("Form", "刷新数据"))
        self.pushButton_2.setText(_translate("Form", "删除人员"))
        self.pushButton_3.setText(_translate("Form", "新增人员"))
        self.pushButton_4.setText(_translate("Form", "退出"))
        # 绑定按钮事件
        # 查询
        self.pushButton.clicked.connect(self.queryAll)
        # 删除
        self.pushButton_2.clicked.connect(self.delRow)
        # 新增
        self.pushButton_3.clicked.connect(self.addRow)
        # 退出程序
        self.pushButton_4.clicked.connect(
            QtCore.QCoreApplication.instance().quit)

    # 创建数据库
    def createDB(self):
        if os.path.exists("managePerson.db") == False:
            try:
                db = QSqlDatabase.addDatabase("QSQLITE")
                db.setDatabaseName("managePerson.db")
                db.open()
                c = QtSql.QSqlQuery()
                c.exec('''
                            CREATE TABLE managePerson(
                                id INT PRIMARY KEY NOT NULL,
                                name TEXT,
                                age INT,
                                address TEXT,
                                begindate DATE,
                                day INT
                            );''')
                # 插入测试数据
                c.exec_(
                    "INSERT INTO managePerson VALUES (20, '张三', 18, '火星', '2020-05-08', 999);")
                c.exec_(
                    "INSERT INTO managePerson VALUES (40, '李四', 19, '天王星', '2020-05-09', 10);")
                c.exec_(
                    "INSERT INTO managePerson VALUES (30, '王五', 22, '海王星', '2020-02-02', 999);")
                db.close()
                print("创建数据库成功!")
            except Exception as e:
                print(e)
        else:
            print("数据库已存在!")

    # 查询所有人员
    def queryAll(self):
        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName("managePerson.db")
        self.model = QSqlTableModel()
        self.tableView.setModel(self.model)
        self.model.setTable("managePerson")
        self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
        self.model.select()

        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '身份证号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '姓名')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '年龄')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '地址')
        self.model.setHeaderData(4, QtCore.Qt.Horizontal, '开始隔离时间')
        self.model.setHeaderData(5, QtCore.Qt.Horizontal, '需要隔离天数')

    # 删除用户
    def delRow(self):
        if self.model:
            try:
                self.model.removeRow(self.tableView.currentIndex().row())
            except Exception as e:
                print(e)
        else:
            self.createDB()

    # 新增用户
    def addRow(self):
        if self.model:
            try:
                self.model.insertRows(self.model.rowCount(), 1)
            except Exception as e:
                print(e)
        else:
            self.createDB()


# 程序入口
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = QWidget()
    ui = manageUI()
    ui.setupUi(form)
    ui.createDB()
    form.show()
    ui.queryAll()
    sys.exit(app.exec())

查询端

from PyQt5 import QtCore, QtGui, QtSql, QtWidgets
import sys
import datetime
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel
from PyQt5.QtWidgets import QMessageBox

# 查询界面GUI


class queryUI(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(800, 500)
        Form.setFixedSize(Form.width(), Form.height())
        self.textEdit = QtWidgets.QTextEdit(Form)
        self.textEdit.setGeometry(QtCore.QRect(10, 80, 781, 341))
        self.textEdit.setObjectName("textEdit")
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(10, 10, 781, 61))
        font = QtGui.QFont()
        font.setFamily(".Heiti GB18030PUA")
        font.setPointSize(22)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(10, 430, 781, 61))
        self.pushButton.setObjectName("pushButton")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "隔离剩余天数查询"))
        self.textEdit.setHtml(_translate("Form", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                                         "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                                         "p, li { white-space: pre-wrap; }\n"
                                         "</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
                                         "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))
        self.label.setText(_translate("Form", "身份证号:"))
        self.pushButton.setText(_translate("Form", "查询剩余隔离天数"))

        self.pushButton.clicked.connect(self.queryLaveDays)

    # 查询剩余天数
    def queryLaveDays(self):
        # 获取文本框值
        personNo = self.textEdit.toPlainText()
        # 连接数据库
        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName("managePerson.db")
        db.open()
        c = QtSql.QSqlQuery()
        c.exec("SELECT name, begindate, day FROM managePerson WHERE id=" + personNo + ";")
        name = "null"
        while c.next():
            name = c.value(0)
            begindate = c.value(1)
            day = c.value(2)
            print(name, begindate, day)
        db.close()
        # 当前日期
        today = datetime.date.today()
        today = datetime.datetime.strptime(str(today), "%Y-%m-%d")
        try:
            # 隔离开始时间
            begindate = datetime.datetime.strptime(begindate, "%Y-%m-%d")
            # 隔离结束时间
            endDate = begindate + datetime.timedelta(days=day)
        except Exception as e:
            print(e)
        if name == "null":
            msg = "请正确输入身份证号!"
        elif endDate > today:
            laveDay = endDate - today
            msg = name + "您好,您的隔离结束时间为" + str(endDate).replace(" 00:00:00", "") + "剩余" + str(
                laveDay).replace(" days, 0:00:00", "") + "天,请耐心等待!"
        else:
            msg = name + "您好,您已结束隔离期!"

        QMessageBox().information(None, "隔离剩余天数查询", msg, QMessageBox.Yes)


# 程序入口
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = QWidget()
    ui = queryUI()
    ui.setupUi(form)
    form.show()
    sys.exit(app.exec())

打包为exe

pip install pyinstaller

使用PyInstaller

pyinstaller的语法:pyinstaller [options] script [script...] | specfile

最简单的用法,在和myscript.py同目录下执行命令:
pyinstaller mycript.py
然后会看到新增加了两个目录build和dist,dist下面的文件就是可以发布的可执行文件,对于上面的命令你会发现dist目录下面有一堆文件,各种都动态库文件和myscrip可执行文件。有时这样感觉比较麻烦,需要打包dist下面的所有东西才能发布,万一丢掉一个动态库就无法运行了,好在pyInstaller支持单文件模式,只需要执行:

pyinstaller -F mycript.py
你会发现dist下面只有一个可执行文件,这个单文件就可以发布了,可以运行在你正在使用的操作系统类似的系统的下面。当然,pyinstaller还有各种选项,有通用选项,如-d选项用于debug。

在执行pyInstaller命令的时候,会在和脚本相同目录下,生成一个.spec文件,该文件会告诉pyinstaller如何处理你的所有脚本,同时包含了命令选项。一般我们不用去理会这个文件,若需要打包数据文件,或者给打包的二进制增加一些Python的运行时选项时...一些高级打包选项时,需要手动编辑.spec文件。可以使用:
pyi-makespec optionsscript [script ...]
创建一个.spec文件,对于手动编辑的.spec文件,我们可以使用下面任意一条命令:
pyinstaller specfile
pyi-build specfile

PyInstaller原理简介

PyInstaller其实就是把python解析器和你自己的脚本打包成一个可执行的文件,和编译成真正的机器码完全是两回事,所以千万不要指望成打包成一个可执行文件会提高运行效率,相反可能会降低运行效率,好处就是在运行者的机器上不用安装python和你的脚本依赖的库。在Linux操作系统下,它主要用的binutil工具包里面的ldd和objdump命令。

PyInstaller输入你指定的的脚本,首先分析脚本所依赖的其他脚本,然后去查找,复制,把所有相关的脚本收集起来,包括Python解析器,然后把这些文件放在一个目录下,或者打包进一个可执行文件里面。

可以直接发布输出的整个文件夹里面的文件,或者生成的可执行文件。你只需要告诉用户,你的应用App是自我包含的,不需要安装其他包,或某个版本的Python,就可以直接运行了。

需要注意的是,PyInstaller打包的执行文件,只能在和打包机器系统同样的环境下。也就是说,不具备可移植性,若需要在不同系统上运行,就必须针对该平台进行打包。

实践问题

  • pyinstaller打包后的exe运行怎么去掉弹出的命令行提示窗口?
        1.如果使用.spec文件的话, 在该文件中找到console=True修改为console=False

        2.如果是直接指定python文件进行pyinstaller打包的话,需要添加—noconsole

        pyinstaller path\\mycode.py--noconsole

        如果想只打包成一个exe:

        pyinstaller -F path\\mycode.py --noconsole

       或:

        pyinstaller -F -wpath\\mycode.py
  • 更换最终exe生成路径
        在cmd中,一开始就要 cd D:\PythonEXE\ 切换到输出文件夹,然后在用上面的代码,说明:各个参数的作用,

        例子:pyinstaller -F -w -pD:\tmp\core-python\libs -i d:\tmp\main.ico main.py

        -F 表示生成单个可执行文件;

        -D  –onedir 创建一个目录,包含exe文件,但会依赖很多文件(默认选项)。

        -w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!;

        -c  –console, –nowindowed 使用控制台,无界面(默认);

        -p 表示你自己自定义需要加载的类路径,一般情况下用不到;

        -i 表示可执行文件的图标。

参考链接:




扫一扫在手机打开当前页