Python设计图书馆管理系统技术文档(五)
5.3 管理功能实现
- 这个程序管理员的功能就3个,添加书籍、淘汰书籍、用户管理。
5.3.1 管理员界面(AdminHome.py)
import sys
import qdarkstyle
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from UserManage import UserManage
from addBookDialog import addBookDialog
from dropBookDialog import dropBookDialog
class AdminHome(QWidget):
def __init__(self):
super().__init__()
self.setUpUI()
def setUpUI(self):
self.resize(500, 600)
self.setWindowTitle("欢迎使用图书馆管理系统")
self.Hlayout = QHBoxLayout()
self.buttonVlayout = QVBoxLayout()
self.setLayout(self.Hlayout)
font = QFont()
font.setPixelSize(16)
self.userManageButton = QPushButton("用户管理")
self.addBookButton = QPushButton("添加书籍")
self.dropBookButton = QPushButton("淘汰书籍")
self.userManageButton.setFont(font)
self.addBookButton.setFont(font)
self.dropBookButton.setFont(font)
self.userManageButton.setFixedWidth(100)
self.userManageButton.setFixedHeight(42)
self.addBookButton.setFixedWidth(100)
self.addBookButton.setFixedHeight(42)
self.dropBookButton.setFixedWidth(100)
self.dropBookButton.setFixedHeight(42)
self.buttonVlayout.addWidget(self.addBookButton)
self.buttonVlayout.addWidget(self.dropBookButton)
self.buttonVlayout.addWidget(self.userManageButton)
# 将三个按钮所在的垂直布局添加到水平布局中
self.Hlayout.addLayout(self.buttonVlayout)
self.addBookButton.clicked.connect(self.addBookButtonClicked)
self.dropBookButton.clicked.connect(self.dropBookButtonClicked)
self.userManageButton.clicked.connect(self.userManage)
def addBookButtonClicked(self):
addDialog = addBookDialog(self)
addDialog.show()
addDialog.exec_()
def dropBookButtonClicked(self):
dropDialog = dropBookDialog(self)
dropDialog.show()
dropDialog.exec_()
def userManage(self):
UserDelete = UserManage(self)
UserDelete.show()
UserDelete.exec_()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./images/MainWindow_1.png"))
app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
mainMindow = AdminHome()
mainMindow.show()
sys.exit(app.exec_())
- 代码分析
- 本页面,就三个按钮。三个按钮对应三个信号槽函数。这三个函数,分别是添加书籍、淘汰书籍、用户管理的类实例。点击相应按钮后,弹出对应窗口。如图。
- 本页面,就三个按钮。三个按钮对应三个信号槽函数。这三个函数,分别是添加书籍、淘汰书籍、用户管理的类实例。点击相应按钮后,弹出对应窗口。如图。
5.3.2 用户管理(UserManage.py)
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import qdarkstyle
from PyQt5.QtSql import *
import time
import sip
class UserManage(QDialog):
# 初始化
def __init__(self, parent=None):
super(UserManage, self).__init__(parent)
self.resize(380, 400)
self.Vlayout = QVBoxLayout()
self.setLayout(self.Vlayout)
self.setWindowTitle("管理用户")
# 用户数
self.userCount = 0
self.oldDeleteId = ""
self.oldDeleteName = ""
self.deleteId = ""
self.deleteName = ""
self.setUpUI()
def setUpUI(self):
self.db = QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName('./db/LibraryManagement.db')
self.db.open()
self.query = QSqlQuery()
self.getResult()
'''1. 表格设置'''
# 定义一个表格
self.tableWidget = QTableWidget()
# 设定表格行数为数据库查询到的user总数
self.tableWidget.setRowCount(self.userCount)
# 设定表格的列数为2列
self.tableWidget.setColumnCount(2)
# 表格的两列表头分别为”学号“、”姓名“
self.tableWidget.setHorizontalHeaderLabels(['学号', '姓名'])
# 然后再设定表不可编辑
self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
# 标题可拉伸
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 整行选中
self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
# 展示表格控件
self.Vlayout.addWidget(self.tableWidget)
self.setRows()
self.deleteUserButton = QPushButton("删 除 用 户")
hlayout = QHBoxLayout()
hlayout.addWidget(self.deleteUserButton, Qt.AlignHCenter)
self.widget = QWidget()
self.widget.setLayout(hlayout)
self.widget.setFixedHeight(48)
font = QFont()
font.setPixelSize(15)
self.deleteUserButton.setFixedHeight(36)
self.deleteUserButton.setFixedWidth(180)
self.deleteUserButton.setFont(font)
self.Vlayout.addWidget(self.widget, Qt.AlignCenter)
# 设置信号
self.deleteUserButton.clicked.connect(self.deleteUser)
self.tableWidget.itemClicked.connect(self.getStudentInfo)
# 返回学生用户的总数量
def getResult(self):
sql = "SELECT StudentId,Name FROM User WHERE IsAdmin=0"
self.query.exec_(sql)
self.userCount = 0
while self.query.next():
self.userCount += 1
# sql = "SELECT StudentId,Name FROM User WHERE IsAdmin=0"
self.query.exec_(sql)
# 一行行的QTableWidgetItem赋值
def setRows(self):
font = QFont()
font.setPixelSize(14)
for i in range(self.userCount):
if self.query.next():
StudentIdItem = QTableWidgetItem(self.query.value(0))
StudentNameItem = QTableWidgetItem(self.query.value(1))
StudentIdItem.setFont(font)
StudentNameItem.setFont(font)
StudentIdItem.setTextAlignment(Qt.AlignCenter)
StudentNameItem.setTextAlignment(Qt.AlignCenter)
self.tableWidget.setItem(i, 0, StudentIdItem)
self.tableWidget.setItem(i, 1, StudentNameItem)
# return
# 在上面的信号槽中,连接下面这个槽函数,就会获取用户信息
# 把要删除的ID和Name赋给变量
def getStudentInfo(self):
# 索引行的ID、姓名
row = self.tableWidget.currentIndex().row()
# 设置滚动,和行数保持一致
self.tableWidget.verticalScrollBar().setSliderPosition(row)
self.getResult()
i = 0
while self.query.next() and i != row:
i = i + 1
# 这段代码和下面对应的代码,有啥作用?
# self.oldDeleteId = self.deleteId
# self.oldDeleteName = self.deleteName
self.deleteId = self.query.value(0)
self.deleteName = self.query.value(1)
# 删除用户
def deleteUser(self):
if self.deleteId == "" and self.deleteName == "":
print(QMessageBox.warning(self, "警告", "请选中要删除的用户"))
return
# elif self.deleteId == self.oldDeleteId and self.deleteName == self.oldDeleteName:
# print(QMessageBox.warning(self, "警告", "该用户信息不存在"))
# return
if QMessageBox.information(self, "提醒", "删除用户:%s,%s\n用户一经删除将无法恢复,是否继续?" % (self.deleteId, self.deleteName),
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.No:
return
# 从User表删除用户
sql = "DELETE FROM User WHERE StudentId='%s'" % self.deleteId
self.query.exec_(sql)
self.db.commit()
# 归还所有书籍
sql = "SELECT * FROM User_Book WHERE StudentId='%s' AND BorrowState=1" % self.deleteId
self.query.exec_(sql)
timeNow = time.strftime('%Y-%m-%d', time.localtime(time.time()))
updateQuery = QSqlQuery()
while self.query.next():
bookId = self.query.value(1)
sql = "UPDATE Book SET NumCanBorrow=NumCanBorrow+1 WHERE BookId='%s'" % bookId
updateQuery.exec_(sql)
self.db.commit()
sql = "UPDATE User_Book SET ReturnTime='%s',BorrowState=0 WHERE StudentId='%s' AND BorrowState=1" % (
timeNow, self.deleteId)
self.query.exec_(sql)
self.db.commit()
print(QMessageBox.information(self, "提醒", "删除用户成功!", QMessageBox.Yes, QMessageBox.Yes))
self.updateUI()
return
# 删除界面
def updateUI(self):
self.getResult()
self.Vlayout.removeWidget(self.widget)
self.Vlayout.removeWidget(self.tableWidget)
sip.delete(self.widget)
sip.delete(self.tableWidget)
# 删除上一个界面,再重新进行表格设置,展示删除后的新界面
self.tableWidget = QTableWidget()
# 设置行数
self.tableWidget.setRowCount(self.userCount)
# 设置列数
self.tableWidget.setColumnCount(2)
# 设置表头
self.tableWidget.setHorizontalHeaderLabels(['学号', '姓名'])
# 不可编辑
self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
# 标题可拉伸
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 整行选中,QAbstractItemView视图
self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
self.Vlayout.addWidget(self.tableWidget)
self.setRows()
"""
和上面的功能一样,删除了上面的界面,还要重新展示按钮,重新绑定一下两个槽函数
:return
"""
self.deleteUserButton = QPushButton("删 除 用 户")
hlayout = QHBoxLayout()
hlayout.addWidget(self.deleteUserButton, Qt.AlignHCenter)
self.widget = QWidget()
self.widget.setLayout(hlayout)
self.widget.setFixedHeight(48)
font = QFont()
font.setPixelSize(15)
self.deleteUserButton.setFixedHeight(36)
self.deleteUserButton.setFixedWidth(180)
self.deleteUserButton.setFont(font)
self.Vlayout.addWidget(self.widget, Qt.AlignCenter)
# 设置信号
self.deleteUserButton.clicked.connect(self.deleteUser)
self.tableWidget.itemClicked.connect(self.getStudentInfo)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./images/MainWindow_1.png"))
app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
mainWindow = UserManage()
mainWindow.show()
sys.exit(app.exec_())
- 代码分析
-
这是一个对话框的窗体控件。只用一个垂直布局(外围红框),然后放入一个QTableWidget控件(淡黄的虚线)。先设置QTableWidgetItem(学号、姓名的单元格),再用数据库sql语句获取非管理员的所有用户getResult(sql之后左侧展示所有的行),放入QTableWidget里面显示setRows(把学号、姓名下面的单元格填入信息)。因为涉及到后面的删除操作,上图说明。
-
这两天阳了,也没吃药,光喝水,第3天,终于阳康了。
-
在setUpUI最后,定义了两个信号槽
self.deleteUserButton.clicked.connect(self.deleteUser) self.tableWidget.itemClicked.connect(self.getStudentInfo)
-
在deleteUser函数里面,完成了如下工作。
- (1)判断是否选择要删除的用户
- (2)在选中删除用户后,点击删除弹出警告提醒。
- (3)接着,在数据库中的Book表中修改还能借阅的数量NumCanBorrow。再把User_Book表中借阅的状态改为0(用户都不在了,为何不删除呢)
- (4)最后,提醒删除成功,接着运行后面的函数方法updateUI()。
-
在updateUI方法中,完成了如下工作。
- (1)删除布局widget和表布局tableWidget。
- (2)再重新进行表格设置,展示删除后的新界面。
- (3)因为在这个函数一开始是删除了布局,所以,再重新生成“删除用户”按钮。
-
至此,完成了这一对话框的分析和学习。
-
5.3.3 添加书籍(addBookDialog)
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import qdarkstyle
import time
from PyQt5.QtSql import *
class addBookDialog(QDialog):
add_book_success_signal = pyqtSignal()
def __init__(self, parent=None):
super(addBookDialog, self).__init__(parent)
self.setUpUI()
# 下面设置用以设置窗口模态类型为半模态,阻塞其他窗口反应半模态
self.setWindowModality(Qt.WindowModal)
self.setWindowTitle("添加书籍")
def setUpUI(self):
# 书名,书号,作者,分类,添加数量.出版社,出版日期
# 书籍分类:哲学类、社会科学类、政治类、法律类、军事类、经济类、文化类、教育类、体育类、语言文字类、艺术类、历史类、地理类、天文学类、生物学类、医学卫生类、农业类
BookCategory = ["哲学", "社会科学", "政治", "法律", "军事", "经济", "文化", "教育", "体育", "语言文字", "艺术",
"历史", "地理", "天文学", "生物学", "医学卫生", "农业"]
self.resize(300, 300)
self.Flayout = QFormLayout()
self.setLayout(self.Flayout)
# Label标签控件
self.titlelabel = QLabel(" 添加书籍")
self.bookNameLabel = QLabel("书 名:")
self.bookIdLabel = QLabel("书 号:")
self.authNameLabel = QLabel("作 者:")
self.categoryLabel = QLabel("分 类:")
self.publisherLabel = QLabel("出 版 社:")
self.publishDateLabel = QLabel("出版日期:")
self.addNumLabel = QLabel("数 量:")
# button控件
self.addBookButton = QPushButton("添 加")
# lineEdit控件
self.bookNameEdit = QLineEdit()
self.bookIdEdit = QLineEdit()
self.authNameEdit = QLineEdit()
# 分类创建的QComboBox,存储整个分类的列表。combo(联合体)
# QComboBox,以占用最少屏幕控件的方式向用户呈现选项列表的方法
self.categoryComboBox = QComboBox()
self.categoryComboBox.addItems(BookCategory)
self.publisherEdit = QLineEdit()
self.publishTime = QDateTimeEdit()
self.publishTime.setDisplayFormat("yyyy-MM-dd")
# self.publishDateEdit = QLineEdit()
self.addNumEdit = QLineEdit()
self.bookNameEdit.setMaxLength(10)
self.bookIdEdit.setMaxLength(6)
self.authNameEdit.setMaxLength(10)
self.publisherEdit.setMaxLength(10)
self.addNumEdit.setMaxLength(12)
self.addNumEdit.setValidator(QIntValidator())
# 添加进formlayout
self.Flayout.addRow("", self.titlelabel)
self.Flayout.addRow(self.bookNameLabel, self.bookNameEdit)
self.Flayout.addRow(self.bookIdLabel, self.bookIdEdit)
self.Flayout.addRow(self.authNameLabel, self.authNameEdit)
self.Flayout.addRow(self.categoryLabel, self.categoryComboBox)
self.Flayout.addRow(self.publisherLabel, self.publisherEdit)
self.Flayout.addRow(self.publishDateLabel, self.publishTime)
self.Flayout.addRow(self.addNumLabel, self.addNumEdit)
self.Flayout.addRow("", self.addBookButton)
# 设置字体
font = QFont()
font.setPixelSize(20)
self.titlelabel.setFont(font)
font.setPixelSize(14)
self.bookNameLabel.setFont(font)
self.bookIdLabel.setFont(font)
self.authNameLabel.setFont(font)
self.categoryLabel.setFont(font)
self.publisherLabel.setFont(font)
self.publishDateLabel.setFont(font)
self.addNumLabel.setFont(font)
self.bookNameEdit.setFont(font)
self.bookIdEdit.setFont(font)
self.authNameEdit.setFont(font)
self.publisherEdit.setFont(font)
self.publishTime.setFont(font)
self.categoryComboBox.setFont(font)
self.addNumEdit.setFont(font)
# button设置
font.setPixelSize(16)
self.addBookButton.setFont(font)
self.addBookButton.setFixedHeight(32)
self.addBookButton.setFixedWidth(140)
# 设置间距
self.titlelabel.setMargin(8)
self.Flayout.setVerticalSpacing(10)
self.addBookButton.clicked.connect(self.addBookButtonCicked)
def addBookButtonCicked(self):
bookName = self.bookNameEdit.text()
bookId = self.bookIdEdit.text()
authName = self.authNameEdit.text()
bookCategory = self.categoryComboBox.currentText()
publisher = self.publisherEdit.text()
publishTime = self.publishTime.text()
addBookNum = self.addNumEdit.text()
if (
bookName == "" or bookId == "" or authName == "" or bookCategory == "" or publisher == "" or publishTime == "" or addBookNum == ""):
print(QMessageBox.warning(self, "警告", "有字段为空,添加失败", QMessageBox.Yes, QMessageBox.Yes))
return
else:
addBookNum = int(addBookNum)
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName('./db/LibraryManagement.db')
db.open()
query = QSqlQuery()
# 如果已存在,则update Book表的现存量,剩余可借量,不存在,则insert Book表,同时insert buyordrop表
sql = "SELECT * FROM Book WHERE BookId='%s'" % bookId
query.exec_(sql)
if query.next():
sql = "UPDATE Book SET NumStorage=NumStorage+%d,NumCanBorrow=NumCanBorrow+%d WHERE BookId='%s'" % (
addBookNum, addBookNum, bookId)
else:
sql = "INSERT INTO book VALUES ('%s','%s','%s','%s','%s','%s',%d,%d,0)" % (
bookName, bookId, authName, bookCategory, publisher, publishTime, addBookNum, addBookNum)
query.exec_(sql)
db.commit()
# 插入droporinsert表
timenow = time.strftime('%Y-%m-%d', time.localtime(time.time()))
sql = "INSERT INTO buyordrop VALUES ('%s','%s',1,%d)" % (bookId, timenow, addBookNum)
query.exec_(sql)
db.commit()
print(QMessageBox.information(self, "提示", "添加书籍成功!", QMessageBox.Yes, QMessageBox.Yes))
self.add_book_success_signal.emit()
self.close()
self.clearEdit()
return
def clearEdit(self):
self.bookNameEdit.clear()
self.bookIdEdit.clear()
self.authNameEdit.clear()
self.addNumEdit.clear()
self.publisherEdit.clear()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./images/MainWindow_1.png"))
app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
mainMindow = addBookDialog()
mainMindow.show()
sys.exit(app.exec_())
- 经过几节的学习,这个对话框控件的学习,就显得比较简单了。布局最后,再定义一个信号槽。槽函数addBookButtonCicked对应“添加”按钮,里面具体完成的工作是,如果这本书图书馆已经有的话,则只是更新数量UPDATE,没有是INSERT。还不要忘记在buyordrop表中增添一个添加书籍的记录。最后再调用函数方法clearEdit,完成一次添加工作。
5.3.4 淘汰书籍(dropBookDialog.py)
-
这个对话框页面,更加简单,布局最后定义两个信号槽。
self.bookIdEdit.textChanged.connect(self.bookIdEditChanged) self.dropBookButton.clicked.connect(self.dropBookButtonClicked)
-
槽函数bookIdEditChanged对应“书号”的文本触发,一旦有这本书的话,马上把对话框各个字段全部更新显示出来。
-
槽函数dropBookButtonClicked是按下“淘汰”按钮后的方法处理。先判断是否选择要淘汰的书籍,还要判断是否超过原有库存数量,这里获取的是book表里的第7个字段NumStorage,超了的话,提醒。然后,就可以删除Book表对应的记录,还不要忘记在buyordrop表中增添一个淘汰书籍的记录。最后再调用函数方法QMessageBox消息提醒,删除成功,关闭完成。