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 评论