山东大学数据库实验三——模拟铁路售票系统

本文详细描述了使用Python、pyMySQL和pyQt5开发的模拟铁路售票系统的开发过程,包括界面设计、数据库连接、用户权限管理及界面之间的通信。还介绍了如何使用qtdesigner设计界面并打包程序。
摘要由CSDN通过智能技术生成

README

本文为记录开发山东大学计算机学院数据库实验三——数据库应用开发的过程,我们小组选择了模拟铁路售票系统这个选题,这个选题算是一个比较简单的题目了,记录一下开发过程,希望能对大家有所启发

概览

该程序主要使用Python开发,应用了pyMySQL连接MySQL数据库,使用pyQt5实现可视化界面

该程序还应用了连接阿里云RDS for MySQL,实现了云端服务、脱机使用,在任意一台Windows主机上都可以运行

该程序主要面向两个用户——普通用户、管理员,两个用户的功能不相同

普通用户功能主要有:购票、退票、账户车票查询、账户管理

管理员功能主要有:管理用户(删除用户、修改用户密码)、管理车次(增加、删除车次)、更新车次信息

页面创建流程

每个页面由page_name.ui、page_name.py、page_name_pre.py三个文件组成

首先适用Pycharm插件qtdesigner设计出页面的大体框架,设计好信号以及槽函数并连接

qtdesigner不建议关闭,如果后续要修改界面相关组成或者信号槽,可以直接在里面编辑

设计完界面之后,保存到项目根目录,在Pycharm中选中该.ui文件,使用外部工具PyUIC生成该页面的.py文件,但是此时该文件并不能直接运行、显示或者被其他界面调用,需要通过驱动程序驱动显示

这时就要创建一个pre.py文件,这里面包含对槽函数、信号的定义、对界面的代码更改以及一些其他格式定义,这里以登录界面login_pre.py为例,讲解驱动程序的结构

该文件所用到的模块一般有:

import sys
from PyQt5.QtGui import QPixmap,QPalette,QFont,QGuiApplication # PyQt相关模块
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
from PyQt5.QtCore import *
from login import Ui_tratic # 这是login界面的驱动程序,若是其他界面,换成界面名字即可

接着连接数据库,这里我使用了阿里云RDS,大家可以使用自己本地的MySQL账户和密码登录

import pymysql
db=pymysql.connect(host="xxxx.mysql.rds.aliyuncs.com",user="alphonza",password="QAZwsx123",database="tratic")
cursor=db.cursor() # 定义游标,后续通过游标访问数据库信息

这里还用到了一个函数,这个函数用以在程序打包的时候,找到图片等资源文件的路径,以使我们可以在代码中访问这些文件,在打包时,将源文件添加到目录中即可:

import os
def get_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except AttributeError:
        base_path = os.path.abspath(".")
    return os.path.normpath(os.path.join(base_path, relative_path))

 定义界面类,以及构造函数:

class MyMainWindow(QMainWindow, Ui_tratic):  # 继承 QMainWindow类和 Ui_tratic界面类
    # 信号定义在这里
    signal_phone=pyqtSignal(str)   # 传给主界面账号、密码等信息
    signal_password=pyqtSignal(str)
    signal_left=pyqtSignal(str)   # 激发显示欢迎语句的信号
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)  # 初始化父类
        self.setupUi(self)  # 继承 Ui_MainWindow 界面类
        self.setWindowTitle("login")# 设置标题

之后可以继续在构造函数中编写其他内容,这些代码是在构建这个界面时就会运行的,比如我的login界面的构造函数里还有:

pix = QPixmap(get_path("assets/铁路.png"))# 导入图片(调用get_path函数)
self.label_3.setPixmap(pix)
self.label_3.setScaledContents(True)
pix1 = QPixmap(get_path("assets/背景.jpg"))  # 导入图片
self.label_4.setPixmap(pix1)
self.label_4.setScaledContents(True)
font = QFont("黑体", 24, 75)
pe = QPalette()
pe.setColor(QPalette.WindowText, Qt.black)  # 设置字体样式
self.label_2.setFont(font)
self.label_5.setFont(font)
self.label.setFont(font)
self.label_2.setPalette(pe)
self.label.setPalette(pe)
self.label_5.setPalette(pe)

类定义中还要包含界面设计的所有槽函数的定义,以下是login_fun定义:

    def login_fun(self):
        '''登录槽函数'''
        phone=self.lineEdit.text() # 获取用户输入
        password=self.lineEdit_2.text()
        # 定义sql语句,sql语句全部用字符串变量描述,后续传给游标
        login_sql = "select keyword from passenger where(phone_number='{}')".format(phone)
        cursor.execute(login_sql)
        password_database = cursor.fetchone()
        if password_database==None:   # 用户不存在或者是管理员账户
            admin_login_sql="select password from admin where(admin_id='{}')".format(phone)
            cursor.execute(admin_login_sql)
            admin_password_database=cursor.fetchone()
            if admin_password_database==None:
                QMessageBox.information(self, "提示", """用户不存在!""")
                return
            if password==admin_password_database[0]: # 是管理员账户
                QMessageBox.information(self, "提示", """登录成功!""")
                import admin_main_interface_pre # 链接另一个界面,admin_main_interface界面
                self.four = admin_main_interface_pre.MyMainWindow() # 用一个变量保存被调用界面的主类
                # 传递信号给被调用界面
                self.signal_phone.connect(self.four.aget_phone)
                self.signal_phone.emit(phone)
                self.signal_password.connect(self.four.aget_password)
                self.signal_password.emit(password)
                self.signal_left.connect(self.four.astart_left)
                self.signal_left.emit("start")
                self.four.show() # 像用户展示被调用界面,有时还需要关闭调用界面
            else:
                QMessageBox.information(self, "提示", """用户不存在!""")
            if password==admin_password_database[0]:
                self.close()
            self.lineEdit_2.clear()
            return
        if password == password_database[0]:   # 登录成功,进入主界面
            QMessageBox.information(self, "提示", """登录成功!""")
            import main_interface_pre
            self.two=main_interface_pre.MyMainWindow()
            self.signal_phone.connect(self.two.get_phone)
            self.signal_phone.emit(phone)
            self.signal_password.connect(self.two.get_password)
            self.signal_password.emit(password)
            self.signal_left.connect(self.two.start_left)
            self.signal_left.emit("start")
            self.two.show()
            self.close()
        else:   # 密码错误
            QMessageBox.warning(self, "提示","""密码错误,请重新输入!""")
            self.lineEdit_2.clear()
        return

以下是创建普通账户、管理员账户的槽函数:

    def create_account(self):
        '''创建账户槽函数'''
        import create_account_pre    # 链接create_account界面
        self.one=create_account_pre.MyMainWindow()
        self.one.show()
        self.close()   #关闭当前界面
    def admin_create_account(self):
        '''创建管理员账户槽函数'''
        import admin_create_account_pre
        self.three=admin_create_account_pre.MyMainWindow()
        self.three.show()
        self.close()

还要在结尾处包含以下代码:

# 设置界面适应系统缩放比例
QGuiApplication.setAttribute(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
if __name__ == '__main__':
    app = QApplication(sys.argv)  # 在 QApplication 方法中使用,创建应用程序对象
    myWin = MyMainWindow()  # 实例化 MyMainWindow 类,创建主窗口
    myWin.show()  # 在桌面显示控件 myWin
    sys.exit(app.exec_())  # 结束进程,退出程序

login界面效果

其他界面的驱动函数编写流程大同小异,根据所需要的功能,编写相应的槽函数实现

其他问题

Q:如何配置两个外部工具?

A:设置里点击外部工具——添加——输入相应指令

qtdesigner配置

pyuic配置


Q:如何使用qtdesigner?

A:可以参照[ PyQt入门教程 ] Qt Designer工具的使用_qtdesigner教程-CSDN博客


Q:如何打包?

A:在根目录中添加内容如下的.spec文件

# -*- mode: python ; coding: utf-8 -*-
a = Analysis( # 这里填写你目录中所有的.py文件
  ['login_pre.py','login.py','create_account.py','create_account_pre.py','main_interface.py','main_interface_pre.py','query.py','query_pre.py','query_result.py','query_result_pre.py','show_result.py','show_result_pre.py','tickets_hold.py','tickets_hold_pre.py','add_trains.py','add_trains_pre.py','admin_create_account.py','admin_create_account_pre.py','admin_main_interface.py','admin_main_interface_pre.py','manage_passenger.py','manage_passenger_pre.py','manage_train.py','manage_train_pre.py','change_password.py','change_password_pre.py','change_password_pa.py','change_password_pa_pre.py'],
    pathex=[],
    binaries=[],
    datas=[('assets','assets')], # 这里填写你的资源存放的文件夹名字
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='tratic', # 这里填写你的程序名字
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

然后在pycharm控制台,cd到根目录,运行如下指令,即可打包完成

pyinstaller xxx.spec

有关qt相关问题可以自行查找书籍资料或者其他博文

LAST

有什么问题可以评论区问喔

这里贴一下我的源码地址

tratic: tratic模拟铁路购票系统

希望能帮到大家!

  • 28
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值