拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 PyQt5 快速开发 - 学生管理系统项目实战报告

PyQt5 快速开发 - 学生管理系统项目实战报告

白鹭 - 2022-02-11 1982 0 0

PyQt5 快速开发 - 学生管理系统项目实战报告

  • 一、登陆界面搭建
  • 二、登陆验证
  • 三、主界面
    • 1、初始化
    • 2、添加控制元件
    • 3、设定函式与信号
    • 4、树的函式
    • 5、右键选项信号槽
    • 6、资料表显示函式
    • 7、运行代码按钮信号槽
    • 8、代码输入框
    • 9、清空按钮与富文本浏览器
  • 四、新建资料表对话框
    • 1、添加控制元件
    • 2、初始化对话框
    • 3、设定控制元件属性
    • 4、确定按钮信号槽
    • 5、连接 UI 表单
  • 五、洗掉记录对话框
  • 六、全部代码

为了实作我的计划,我使用 PyQt5 撰写程序,制作了一个简易 GUI 的 学生管理系统,作为 2021 年最后一个程序,运用到了我在2021年所学的大部分知识,绝对算得上是压轴程序,但是并没有给界面做美化,

  • 登录界面
    在这里插入图片描述
  • 主界面
    在这里插入图片描述

一、登陆界面搭建

登录界面用的 Designer 可视化程序搭建的,动动鼠标就能轻松搭建出一个用户界面,
在这里插入图片描述
然后在 Pycharm 中用 PyUIC 把 .ui 档案转为 .py 档案,

二、登陆验证

在界面程序中给两个按钮(登录 和 退出)系结信号

# 退出
self.retranslateUi(widget)
self.pushButton_2.clicked.connect(widget.close)  # type: ignore

# 登录
self.pushButton.clicked.connect(self.login_in)  # type: ignore
self.pushButton.setShortcut('Return')

写登录信号槽

# 验证登录
def login_in(self):
	# 全域变量传参给其他所有界面
    global gl_db
    global gl_host
    global gl_pwd
    global gl_user
    global gl_port

    gl_db = self.lineEdit_5.text()
    gl_host = self.lineEdit_3.text()
    gl_pwd = self.lineEdit_2.text()
    gl_user = self.lineEdit.text()
    try:
        port = int(self.lineEdit_4.text())
        try:
            conn = pymysql.connect(host=gl_host, port=gl_port, db=gl_db, user=gl_user, password=gl_pwd)
            print('登录数据库{}成功'.format(gl_db))
            self.messageDialog('提示', '登录数据库{}成功'.format(gl_db))
            conn.close()
            del conn
            # 登录成功后跳转到主界面
            self.main_show = Fulling()
            self.main_show.show()
            mainWindow.close()
        except pymysql.err.OperationalError:
            print('由于目标计算机积极拒绝,无法连接,')
            self.messageDialog('警告', '由于目标计算机积极拒绝,无法连接,')
    except ValueError:
        print('埠号错误')
        self.messageDialog('警告', '埠号错误')
    except Exception as err:
        print('错误:', err)
        self.messageDialog('警告', str(err))

# 提示信息
def messageDialog(self, title, text):
    msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, text)
    msg_box.exec_()

登录逻辑程序代码

class Login(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(600, 400)  # 禁止拖动
        self.setWindowIcon(QtGui.QIcon('./img/001.ico'))  # 设定表单标题图示
        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)  # 禁用最大化

        # 背景图片
        image = QtGui.QPixmap()
        image.load(r'./img/login_bg.jpg')
        bg = QtGui.QPalette()
        bg.setBrush(self.backgroundRole(), QtGui.QBrush(image))
        self.setPalette(bg)
        self.setAutoFillBackground(True)


if __name__ == '__main__':
    gl_db = ''
    gl_host = ''
    gl_pwd = ''
    gl_user = ''
    gl_port = 0
    # 创建 QApplication 类的实体
    logapp = QApplication(sys.argv)
    # 创建表单
    mainWindow = Login()
    # 关联login
    ui = Ui_widget()
    ui.setupUi(mainWindow)
    # 打开表单
    mainWindow.show()
    # 退出表单
    sys.exit(logapp.exec_())

在这里插入图片描述

三、主界面

因为主界面涉及到的控制元件比较复杂,所以直接用代码写出来,不使用 Designer,

1、初始化

  • 先给界面初始化,标题,视窗大小,图示,控制元件,并且连接数据库
class Fulling(QWidget):
	# 初始化
    def __init__(self):
        super().__init__()
        # 视窗标题
        self.setWindowTitle('学生管理系统')
        # 视窗大小
        self.resize(720, 600)
        # 视窗居中
        self.center()
        # 图示
        self.setWindowIcon(QIcon('./img/001.ico'))
        # 连接数据库
        self.conn = pymysql.connect(host=gl_host, port=gl_port, user=gl_user, password=gl_pwd, db=gl_db)
        self.tree_view = None
        self.table_view = None
        self.queryModel = None
        self.text_edit = None
        self.run_button = None
        self.row = None
        self.vol = None
        self.text_browser = None
        self.clear_button = None
        self.add_db_view = None
        self.del_db_view = None
        self.cur = self.conn.cursor()
        self.init_ui()

	# 视窗居中
    def center(self):
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move(round((screen.width() - size.width()) / 2), round((screen.height() - size.height()) / 2))

	# 警告信息
    @staticmethod
    def message_dialog(title, text):
        msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, text)
        msg_box.exec_()

2、添加控制元件

  • 视窗添加控制元件,并为他们布局
	# 视窗布局
	def create_window(self):
	    # 设定树属性
	    self.tree_view = QTreeWidget()
	    # 设定表格属性
	    self.table_view = QTableWidget()
	    # 设定文本框
	    self.text_edit = QTextEdit()
	    # 设定运行按钮
	    self.run_button = QPushButton('运行所有代码')
	    # 设定清空按钮
	    self.clear_button = QPushButton('清空代码')
	    # 设定查看文本
	    self.text_browser = QTextBrowser()
	    # 表格宽度自适应
	    self.table_view.horizontalHeader().setStretchLastSection(True)
	    self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
	
	    # 左侧布局
	    left_layout = QVBoxLayout()
	    left_layout.addWidget(self.tree_view, 15)
	    left_layout.addWidget(self.text_browser, 9)
	
	    # 右中
	    mid_layout = QHBoxLayout()
	    mid_layout.addWidget(self.run_button)
	    mid_layout.addWidget(self.clear_button)
	    mid_layout.addWidget(QSplitter())
	
	    # 右侧布局
	    right_layout = QVBoxLayout()
	    right_layout.addWidget(self.table_view, 15)
	    right_layout.addLayout(mid_layout, 1)
	    right_layout.addWidget(self.text_edit, 8)
	
	    # 创建界面
	    layout = QHBoxLayout(self)
	    layout.addLayout(left_layout, 1)
	    layout.addLayout(right_layout, 3)
	    self.setLayout(layout)

3、设定函式与信号

  • 给每个控制元件添加自己的函式和信号
	# 设定视窗主要部件和信号
	def init_ui(self):
	    # 创建视窗
	    self.create_window()
	    # 设定树
	    self.set_tree_view()
	    # 设定表格
	    self.set_table_view()
	    # 设定文本框
	    self.set_text_edit()
	    # 创建运行按钮
	    self.set_run_button()
	    # 创建清空按钮
	    self.set_clear_button()
	    # 创建查看文本
	    self.set_text_browser()
	
	    # 信号槽
	    self.tree_view.clicked.connect(self.on_tree_clicked)
	    self.run_button.clicked.connect(self.run_program)
	    self.clear_button.clicked.connect(self.clear_all)
	
	    # 给树添加右键
	    self.tree_view.setContextMenuPolicy(Qt.CustomContextMenu)
	    self.tree_view.customContextMenuRequested.connect(self.right_menu_show)
	
	    # 运行按钮快捷键
	    self.run_button.setShortcut('F5')

4、树的函式

  • 让树能够显示所有的资料表
  • 本来想的是把所有的资料表、视图、事件等都显示出来,但是这里我只写了显示资料表
    # 树
    def set_tree_view(self):
        # 树行数
        self.tree_view.setColumnCount(1)
        # 树标题
        self.tree_view.setHeaderLabel(gl_db + '.db')
        # 设定根节点
        root = QtWidgets.QTreeWidgetItem(self.tree_view)
        root.setText(0, '表')  # 只有一列
        root.setIcon(0, QIcon('img/db_logo.png'))
        # 创建游标
        cursor = self.conn.cursor()
        cursor.execute("show tables;")
        res = cursor.fetchall()
        # 遍历表
        for i in range(len(res)):
            child = QtWidgets.QTreeWidgetItem(root)  # 指定父目录
            child.setText(0, res[i][0])
            child.setText(1, '{}'.format(i + 1))
            child.setIcon(0, QIcon('img/table_logo.png'))
        # 树默认收缩
        root.setExpanded(False)
        # 树根节点
        self.tree_view.addTopLevelItem(root)
  • 树中左键单击展开树 或 打开资料表
    在这里插入图片描述
    # 树左键单击
    def on_tree_clicked(self):
        try:
        	# 获取树中的内容
            item = self.tree_view.currentItem()
            # 如果单击的是根目录则展开或收缩树
            if item.text(0) == '表':
                print('左键单击{}'.format(item.text(0)))
                if self.tree_view.currentItem().isExpanded():
                    self.tree_view.collapseAll()
                else:
                    self.tree_view.expandAll()
                    
            # 如果单击的是表则打开表
            else:
                item = self.tree_view.currentItem()
                self.cur.execute('select * from ' + item.text(0))
                self.select_run()
                print('左键单击{}'.format(item.text(0)))
        except Exception as e:
            print('树左键单击{}'.format(e))
            self.message_dialog('提示', '请先输入资料')
  • 树中右键单击显示 右键选单选项
    在这里插入图片描述
    # 树右键单击
    def right_menu_show(self):
        try:
            item = self.tree_view.currentItem()
            if item.text(0) == '表':
                print('右键单击{}'.format(item.text(0)))
                # 添加选单选项
                self.contextMenu = QMenu()
                self.add_db = self.contextMenu.addAction(u'新建资料表')
                self.flash_db = self.contextMenu.addAction(u'重绘')
                self.close_db = self.contextMenu.addAction(u'退出')
                self.contextMenu.popup(QCursor.pos())
                # 给选单选项系结信号
                self.add_db.triggered.connect(self.add_database)  # type:ignore
                self.flash_db.triggered.connect(self.flash)  # type:ignore
                self.close_db.triggered.connect(self.close_database)  # type:ignore
                self.contextMenu.show()

            else:
                # 资料表的右键
                print('右键单击{},序号是{}'.format(item.text(0), item.text(1)))
                self.contextMenu = QMenu()
                self.open = self.contextMenu.addAction(u'打开表')
                self.drop = self.contextMenu.addAction(u'洗掉表')
                self.add = self.contextMenu.addAction(u'添加记录')
                self.delete = self.contextMenu.addAction(u'洗掉记录')
                self.update = self.contextMenu.addAction(u'更改记录')
                self.select = self.contextMenu.addAction(u'查询记录')
                self.open.triggered.connect(self.open_table)  # type:ignore
                self.drop.triggered.connect(self.drop_table)  # type:ignore
                self.add.triggered.connect(self.add_table)  # type:ignore
                self.delete.triggered.connect(self.delete_table)  # type:ignore
                self.update.triggered.connect(self.update_table)  # type:ignore
                self.select.triggered.connect(self.select_table)  # type:ignore
                self.contextMenu.popup(QCursor.pos())
                self.contextMenu.show()

        except Exception as e:
            print(e)

5、右键选项信号槽

  • 根目录的右键选单
    在这里插入图片描述
    # 树重绘
    def flash(self):
        """添加资料表后的重绘操作"""
        print('重绘')
        item = self.tree_view.currentItem()
        root = QtWidgets.QTreeWidgetItem(self.tree_view)
        root.setText(0, '表')  # 只有一列
        root.setIcon(0, QIcon('img/db_logo.png'))
        cursor = self.conn.cursor()
        cursor.execute("show tables;")
        res = cursor.fetchall()

        # 清除树
        curr_node = self.tree_view.currentItem()
        root_index = self.tree_view.indexOfTopLevelItem(curr_node)
        self.tree_view.takeTopLevelItem(root_index)

		# 再把重绘获取的树放上去
        for i in range(len(res)):
            child = QtWidgets.QTreeWidgetItem(root)  # 指定父目录
            child.setText(0, res[i][0])
            child.setText(1, '{}'.format(i + 1))
            child.setIcon(0, QIcon('img/table_logo.png'))

    # 新建资料表 这里要用另外的视窗作为对话框,在第四点
    def add_database(self):
        try:
        	# 打开对话框
            self.add_db_view = AdDB()
            add_ui = Ui_add_db_object()
            add_ui.setupUi(self.add_db_view)
            self.add_db_view.show()
        except Exception as e:
            print(e)

        print('新建资料表')

    # 退出资料表
    def close_database(self):
        reply = QMessageBox.question(self, '退出', '确定退出', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            sender = self.sender()
            main_app_db = QApplication.instance()
            main_app_db.quit()
        print('退出资料表')
  • 资料表的右键选单,下面四个操作没有写完,因为需要新建一个对话框
    在这里插入图片描述
    # 右键打开
    def open_table(self):
        item = self.tree_view.currentItem()
        self.cur.execute('select * from ' + item.text(0))
        self.select_run()
        print('打开 {}'
							
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *