图书管理系统(python轻量版保姆级教程)
·
本文适合:计算机相关专业本科 / 专科毕业设计、课程设计、Python 新手 | 全程内置库,无第三方依赖,双击即可运行
本文分享的版本基于 Python+SQLite+Tkinter 实现,全程使用 Python 内置库,无任何第三方依赖,整个项目体积不足 100KB,无需安装数据库服务、无需配置复杂环境,双击即可启动,完美适配毕业设计与课程设计需求。
项目核心信息
| 项目 | 说明 |
|---|---|
| 开发语言 | Python 3.8+(兼容所有 3.x 版本) |
| 数据库 | SQLite(本地文件库,自动生成,无需部署) |
| 界面框架 | Tkinter(Python 内置,无需额外安装) |
| 项目体积 | 核心代码<25KB,数据库文件<100KB |
| 核心功能 | 图书增删改查、读者管理、借阅 / 归还、数据持久化 |
| 运行方式 | 双击运行,无需虚拟环境、无需额外依赖 |
技术栈选型
- Python:语法简洁、生态完善,内置 Tkinter 和 SQLite,轻量易上手,适合快速开发桌面应用。
- SQLite:轻量级文件型数据库,无需独立服务,数据直接存储在本地文件中,适合小型系统的数据持久化。
- Tkinter:Python 官方内置 GUI 库,无需额外安装,跨平台兼容性好,能快速搭建基础交互界面。
核心功能模块
1. 图书管理模块
- 图书信息添加(书号、书名、作者、出版社、库存)
- 图书信息删除 / 修改
- 图书列表实时展示与刷新
2. 读者管理模块
- 读者信息添加(读者 ID、姓名、联系电话)
- 读者信息删除
- 读者列表实时展示与刷新
3. 借阅归还模块
- 图书借阅(自动记录借阅时间)
- 图书归还(自动更新归还时间)
- 借阅记录全程追溯与展示
核心代码实现(以下为拆分代码,整合代码请于文章结尾处下载)
1. 数据库初始化与操作封装
import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
from datetime import datetime
# 本地数据库文件(自动生成)
DB_FILE = "library.db"
def init_database():
"""初始化数据库,创建表结构与默认管理员"""
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
# 管理员表(默认账号:admin,密码:123456)
cursor.execute('''CREATE TABLE IF NOT EXISTS admin
(id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password TEXT NOT NULL)''')
cursor.execute("INSERT OR IGNORE INTO admin (username, password) VALUES (?, ?)", ("admin", "123456"))
# 图书表
cursor.execute('''CREATE TABLE IF NOT EXISTS books
(book_id TEXT PRIMARY KEY,
book_name TEXT NOT NULL,
author TEXT NOT NULL,
publisher TEXT NOT NULL,
stock INTEGER NOT NULL DEFAULT 0)''')
# 读者表
cursor.execute('''CREATE TABLE IF NOT EXISTS readers
(reader_id TEXT PRIMARY KEY,
reader_name TEXT NOT NULL,
phone TEXT)''')
# 借阅记录表
cursor.execute('''CREATE TABLE IF NOT EXISTS borrow_records
(id INTEGER PRIMARY KEY AUTOINCREMENT,
reader_id TEXT NOT NULL,
book_id TEXT NOT NULL,
borrow_time TEXT NOT NULL,
return_time TEXT DEFAULT '未归还',
FOREIGN KEY (reader_id) REFERENCES readers(reader_id),
FOREIGN KEY (book_id) REFERENCES books(book_id))''')
conn.commit()
conn.close()
def execute_sql(sql, params=()):
"""执行增删改SQL语句"""
try:
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
cursor.execute(sql, params)
conn.commit()
conn.close()
return True
except Exception as e:
messagebox.showerror("错误", f"操作失败:{str(e)}")
return False
def query_sql(sql, params=()):
"""执行查询SQL语句"""
try:
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
cursor.execute(sql, params)
result = cursor.fetchall()
conn.close()
return result
except Exception as e:
messagebox.showerror("错误", f"查询失败:{str(e)}")
return []
2. GUI 界面与业务逻辑实现
class LibrarySystemUI:
def __init__(self, root):
self.root = root
self.root.title("📚 图书管理系统 - 毕业设计版")
self.root.geometry("800x600")
self.root.resizable(False, False)
# 创建主菜单
main_menu = tk.Menu(root)
root.config(menu=main_menu)
# 图书管理菜单
book_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="📖 图书管理", menu=book_menu)
book_menu.add_command(label="图书增删改查", command=self.show_book_manage)
# 读者管理菜单
reader_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="👤 读者管理", menu=reader_menu)
reader_menu.add_command(label="读者增删查", command=self.show_reader_manage)
# 借阅归还菜单
borrow_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="📝 借阅归还", menu=borrow_menu)
borrow_menu.add_command(label="借阅/归还操作", command=self.show_borrow_return)
# 初始欢迎界面
self.show_welcome_page()
def clear_frame(self):
"""清空当前窗口内容(保留菜单)"""
for widget in self.root.winfo_children():
if widget.winfo_class() != "Menu":
widget.destroy()
def show_welcome_page(self):
"""显示欢迎界面"""
self.clear_frame()
welcome_frame = tk.Frame(self.root)
welcome_frame.pack(fill=tk.BOTH, expand=True)
tk.Label(welcome_frame, text="📚 图书管理系统", font=("微软雅黑", 32, "bold"), fg="#2E86AB").pack(pady=80)
tk.Label(welcome_frame, text="毕业设计专用 · Python轻量版", font=("微软雅黑", 14), fg="#7F8C8D").pack(pady=20)
tk.Label(welcome_frame, text="👉 点击顶部菜单开始操作", font=("微软雅黑", 12), fg="#E74C3C").pack(pady=40)
# 图书管理页面
def show_book_manage(self):
self.clear_frame()
# 输入区域
input_frame = tk.Frame(self.root, padx=20, pady=10)
input_frame.pack(fill=tk.X)
tk.Label(input_frame, text="书号:").grid(row=0, column=0, padx=5, pady=5)
self.book_id = tk.Entry(input_frame, width=10)
self.book_id.grid(row=0, column=1, padx=5, pady=5)
tk.Label(input_frame, text="书名:").grid(row=0, column=2, padx=5, pady=5)
self.book_name = tk.Entry(input_frame, width=20)
self.book_name.grid(row=0, column=3, padx=5, pady=5)
tk.Label(input_frame, text="作者:").grid(row=1, column=0, padx=5, pady=5)
self.book_author = tk.Entry(input_frame, width=10)
self.book_author.grid(row=1, column=1, padx=5, pady=5)
tk.Label(input_frame, text="出版社:").grid(row=1, column=2, padx=5, pady=5)
self.book_pub = tk.Entry(input_frame, width=20)
self.book_pub.grid(row=1, column=3, padx=5, pady=5)
tk.Label(input_frame, text="库存:").grid(row=2, column=0, padx=5, pady=5)
self.book_stock = tk.Entry(input_frame, width=10)
self.book_stock.grid(row=2, column=1, padx=5, pady=5)
# 操作按钮
tk.Button(input_frame, text="添加图书", command=self.add_book, bg="#2ECC71", fg="white", width=10).grid(row=2, column=2, padx=5)
tk.Button(input_frame, text="删除图书", command=self.del_book, bg="#E74C3C", fg="white", width=10).grid(row=2, column=3, padx=5)
tk.Button(input_frame, text="修改图书", command=self.update_book, bg="#F39C12", fg="white", width=10).grid(row=2, column=4, padx=5)
tk.Button(input_frame, text="刷新列表", command=self.load_book_list, bg="#3498DB", fg="white", width=10).grid(row=2, column=5, padx=5)
# 表格展示区域
table_frame = tk.Frame(self.root, padx=20, pady=10)
table_frame.pack(fill=tk.BOTH, expand=True)
# 表格配置
columns = ("book_id", "book_name", "author", "publisher", "stock")
self.book_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=15)
# 设置表头
self.book_tree.heading("book_id", text="书号")
self.book_tree.heading("book_name", text="书名")
self.book_tree.heading("author", text="作者")
self.book_tree.heading("publisher", text="出版社")
self.book_tree.heading("stock", text="库存")
# 设置列宽
self.book_tree.column("book_id", width=100)
self.book_tree.column("book_name", width=200)
self.book_tree.column("author", width=100)
self.book_tree.column("publisher", width=200)
self.book_tree.column("stock", width=80)
# 滚动条
scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.book_tree.yview)
self.book_tree.configure(yscrollcommand=scrollbar.set)
self.book_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 加载图书列表
self.load_book_list()
# 图书管理 - 加载列表
def load_book_list(self):
"""加载所有图书到表格"""
# 清空原有数据
for item in self.book_tree.get_children():
self.book_tree.delete(item)
# 查询数据
books = query_sql("SELECT * FROM books")
# 插入数据
for book in books:
self.book_tree.insert("", tk.END, values=book)
# 图书管理 - 添加
def add_book(self):
bid = self.book_id.get().strip()
bname = self.book_name.get().strip()
bau = self.book_author.get().strip()
bpub = self.book_pub.get().strip()
bstock = self.book_stock.get().strip()
if not all([bid, bname, bau, bpub, bstock]):
messagebox.showwarning("提示", "请填写所有字段!")
return
# 执行添加
sql = "INSERT INTO books (book_id, book_name, author, publisher, stock) VALUES (?, ?, ?, ?, ?)"
if execute_sql(sql, (bid, bname, bau, bpub, int(bstock))):
messagebox.showinfo("成功", "图书添加成功!")
self.load_book_list()
# 清空输入框
self.book_id.delete(0, tk.END)
self.book_name.delete(0, tk.END)
self.book_author.delete(0, tk.END)
self.book_pub.delete(0, tk.END)
self.book_stock.delete(0, tk.END)
# 图书管理 - 删除
def del_book(self):
bid = self.book_id.get().strip()
if not bid:
messagebox.showwarning("提示", "请输入要删除的书号!")
return
# 执行删除
sql = "DELETE FROM books WHERE book_id=?"
if execute_sql(sql, (bid,)):
messagebox.showinfo("成功", "图书删除成功!")
self.load_book_list()
self.book_id.delete(0, tk.END)
# 图书管理 - 修改
def update_book(self):
bid = self.book_id.get().strip()
bname = self.book_name.get().strip()
bau = self.book_author.get().strip()
bpub = self.book_pub.get().strip()
bstock = self.book_stock.get().strip()
if not bid:
messagebox.showwarning("提示", "请输入要修改的书号!")
return
# 执行修改
sql = "UPDATE books SET book_name=?, author=?, publisher=?, stock=? WHERE book_id=?"
if execute_sql(sql, (bname, bau, bpub, int(bstock), bid)):
messagebox.showinfo("成功", "图书修改成功!")
self.load_book_list()
# 读者管理页面
def show_reader_manage(self):
self.clear_frame()
# 输入区域
input_frame = tk.Frame(self.root, padx=20, pady=10)
input_frame.pack(fill=tk.X)
# 标签 + 输入框
tk.Label(input_frame, text="读者ID:", font=("微软雅黑", 10)).grid(row=0, column=0, padx=5, pady=5)
self.reader_id = tk.Entry(input_frame, width=10)
self.reader_id.grid(row=0, column=1, padx=5, pady=5)
tk.Label(input_frame, text="读者姓名:", font=("微软雅黑", 10)).grid(row=0, column=2, padx=5, pady=5)
self.reader_name = tk.Entry(input_frame, width=20)
self.reader_name.grid(row=0, column=3, padx=5, pady=5)
tk.Label(input_frame, text="联系电话:", font=("微软雅黑", 10)).grid(row=1, column=0, padx=5, pady=5)
self.reader_phone = tk.Entry(input_frame, width=20)
self.reader_phone.grid(row=1, column=1, padx=5, pady=5)
# 操作按钮
tk.Button(input_frame, text="添加读者", command=self.add_reader, bg="#2ECC71", fg="white", width=10).grid(row=1, column=2, padx=5)
tk.Button(input_frame, text="删除读者", command=self.del_reader, bg="#E74C3C", fg="white", width=10).grid(row=1, column=3, padx=5)
tk.Button(input_frame, text="刷新列表", command=self.load_reader_list, bg="#3498DB", fg="white", width=10).grid(row=1, column=4, padx=5)
# 表格展示区域
table_frame = tk.Frame(self.root, padx=20, pady=10)
table_frame.pack(fill=tk.BOTH, expand=True)
# 表格配置
columns = ("reader_id", "reader_name", "phone")
self.reader_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=15)
# 设置表头
self.reader_tree.heading("reader_id", text="读者ID")
self.reader_tree.heading("reader_name", text="读者姓名")
self.reader_tree.heading("phone", text="联系电话")
# 设置列宽
self.reader_tree.column("reader_id", width=150)
self.reader_tree.column("reader_name", width=200)
self.reader_tree.column("phone", width=200)
# 滚动条
scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.reader_tree.yview)
self.reader_tree.configure(yscrollcommand=scrollbar.set)
self.reader_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 加载读者列表
self.load_reader_list()
# 读者管理 - 加载列表
def load_reader_list(self):
"""加载所有读者到表格"""
# 清空原有数据
for item in self.reader_tree.get_children():
self.reader_tree.delete(item)
# 查询数据
readers = query_sql("SELECT * FROM readers")
# 插入数据
for reader in readers:
self.reader_tree.insert("", tk.END, values=reader)
# 读者管理 - 添加
def add_reader(self):
rid = self.reader_id.get().strip()
rname = self.reader_name.get().strip()
rphone = self.reader_phone.get().strip()
if not all([rid, rname, rphone]):
messagebox.showwarning("提示", "请填写所有字段!")
return
# 执行添加
sql = "INSERT INTO readers (reader_id, reader_name, phone) VALUES (?, ?, ?)"
if execute_sql(sql, (rid, rname, rphone)):
messagebox.showinfo("成功", "读者添加成功!")
self.load_reader_list()
# 清空输入框
self.reader_id.delete(0, tk.END)
self.reader_name.delete(0, tk.END)
self.reader_phone.delete(0, tk.END)
# 读者管理 - 删除
def del_reader(self):
rid = self.reader_id.get().strip()
if not rid:
messagebox.showwarning("提示", "请输入要删除的读者ID!")
return
# 执行删除
sql = "DELETE FROM readers WHERE reader_id=?"
if execute_sql(sql, (rid,)):
messagebox.showinfo("成功", "读者删除成功!")
self.load_reader_list()
self.reader_id.delete(0, tk.END)
# 借阅归还页面
def show_borrow_return(self):
self.clear_frame()
# 输入区域
input_frame = tk.Frame(self.root, padx=20, pady=10)
input_frame.pack(fill=tk.X)
# 标签 + 输入框
tk.Label(input_frame, text="读者ID:", font=("微软雅黑", 10)).grid(row=0, column=0, padx=5, pady=5)
self.br_reader_id = tk.Entry(input_frame, width=10)
self.br_reader_id.grid(row=0, column=1, padx=5, pady=5)
tk.Label(input_frame, text="书号:", font=("微软雅黑", 10)).grid(row=0, column=2, padx=5, pady=5)
self.br_book_id = tk.Entry(input_frame, width=10)
self.br_book_id.grid(row=0, column=3, padx=5, pady=5)
# 操作按钮
tk.Button(input_frame, text="借阅图书", command=self.borrow_book, bg="#2ECC71", fg="white", width=10).grid(row=0, column=4, padx=5)
tk.Button(input_frame, text="归还图书", command=self.return_book, bg="#F39C12", fg="white", width=10).grid(row=0, column=5, padx=5)
tk.Button(input_frame, text="刷新记录", command=self.load_borrow_list, bg="#3498DB", fg="white", width=10).grid(row=0, column=6, padx=5)
# 表格展示区域
table_frame = tk.Frame(self.root, padx=20, pady=10)
table_frame.pack(fill=tk.BOTH, expand=True)
# 表格配置
columns = ("reader_id", "book_id", "borrow_time", "return_time")
self.borrow_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=15)
# 设置表头
self.borrow_tree.heading("reader_id", text="读者ID")
self.borrow_tree.heading("book_id", text="书号")
self.borrow_tree.heading("borrow_time", text="借阅时间")
self.borrow_tree.heading("return_time", text="归还时间")
# 设置列宽
self.borrow_tree.column("reader_id", width=150)
self.borrow_tree.column("book_id", width=150)
self.borrow_tree.column("borrow_time", width=200)
self.borrow_tree.column("return_time", width=200)
# 滚动条
scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.borrow_tree.yview)
self.borrow_tree.configure(yscrollcommand=scrollbar.set)
self.borrow_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 加载借阅记录
self.load_borrow_list()
# 借阅归还 - 加载列表
def load_borrow_list(self):
"""加载所有借阅记录到表格"""
# 清空原有数据
for item in self.borrow_tree.get_children():
self.borrow_tree.delete(item)
# 查询数据
records = query_sql("SELECT reader_id, book_id, borrow_time, return_time FROM borrow_records")
# 插入数据
for record in records:
self.borrow_tree.insert("", tk.END, values=record)
# 借阅归还 - 借阅
def borrow_book(self):
rid = self.br_reader_id.get().strip()
bid = self.br_book_id.get().strip()
if not all([rid, bid]):
messagebox.showwarning("提示", "请填写读者ID和书号!")
return
# 检查读者和图书是否存在
reader_exist = query_sql("SELECT * FROM readers WHERE reader_id=?", (rid,))
book_exist = query_sql("SELECT * FROM books WHERE book_id=?", (bid,))
if not reader_exist:
messagebox.showerror("错误", "读者不存在!")
return
if not book_exist:
messagebox.showerror("错误", "图书不存在!")
return
# 生成借阅时间
borrow_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 执行借阅
sql = "INSERT INTO borrow_records (reader_id, book_id, borrow_time) VALUES (?, ?, ?)"
if execute_sql(sql, (rid, bid, borrow_time)):
messagebox.showinfo("成功", "图书借阅成功!")
self.load_borrow_list()
# 清空输入框
self.br_reader_id.delete(0, tk.END)
self.br_book_id.delete(0, tk.END)
# 借阅归还 - 归还
def return_book(self):
rid = self.br_reader_id.get().strip()
bid = self.br_book_id.get().strip()
if not all([rid, bid]):
messagebox.showwarning("提示", "请填写读者ID和书号!")
return
# 检查是否有未归还的记录
record_exist = query_sql("SELECT * FROM borrow_records WHERE reader_id=? AND book_id=? AND return_time='未归还'", (rid, bid))
if not record_exist:
messagebox.showerror("错误", "无未归还的该图书记录!")
return
# 生成归还时间
return_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 执行归还
sql = "UPDATE borrow_records SET return_time=? WHERE reader_id=? AND book_id=? AND return_time='未归还'"
if execute_sql(sql, (return_time, rid, bid)):
messagebox.showinfo("成功", "图书归还成功!")
self.load_borrow_list()
# 清空输入框
self.br_reader_id.delete(0, tk.END)
self.br_book_id.delete(0, tk.END)
# 程序入口
if __name__ == "__main__":
init_database()
root = tk.Tk()
app = LibrarySystemUI(root)
root.mainloop()
本地运行教程(新手友好)
步骤 1:环境准备
- 安装 Python 3.8+(官网下载:https://www.python.org/downloads/)
- 无需安装任何第三方库(Tkinter、SQLite 均为 Python 内置)
步骤 2:运行代码
- 新建文件夹,将完整代码保存为
library_system.py - 双击
library_system.py,系统自动生成library.db数据库文件 - 首次运行后,即可通过顶部菜单进行图书管理、读者管理、借阅归还等操作
步骤 3:功能测试
- 图书管理:输入书号、书名等信息,点击「添加图书」即可新增
- 读者管理:输入读者 ID、姓名、电话,点击「添加读者」即可新增
- 借阅归还:输入读者 ID 和书号,点击「借阅图书」/「归还图书」即可操作
📸 运行效果截图



完善/优化建议:
- 权限控制:添加管理员 / 普通用户分级权限,密码加密存储(使用
hashlib库) - 数据校验:增加手机号、书号格式校验,库存不足时禁止借阅
- 报表导出:将借阅记录导出为 Excel(使用
xlwt/OpenPyXL库) - 到期提醒:添加图书借阅到期自动提醒功能
- 界面优化:改用 PyQt5/Streamlit 实现更美观的交互界面
- 数据库升级:替换为 MySQL/PostgreSQL,支持多用户远程访问
总结:
- 本系统基于 Python 内置库实现,体积小、易部署,完美适配毕业设计需求;
- 代码结构清晰、注释完善,新手易理解、易扩展,可作为 Python 桌面应用开发的入门案例;
- 核心功能覆盖图书管理全流程,可直接作为毕业设计基础版本,也可按需扩展功能。
完整项目代码:
# 整合版:图书管理系统(可直接运行)
import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
from datetime import datetime
# ===================== 核心配置 =====================
# 本地数据库文件(自动生成,体积<100KB)
DB_FILE = "library.db"
# ===================== 数据库初始化 =====================
def init_database():
"""初始化数据库,创建表结构与默认管理员"""
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
# 1. 管理员表(默认账号:admin,密码:123456)
cursor.execute('''CREATE TABLE IF NOT EXISTS admin
(id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password TEXT NOT NULL)''')
# 插入默认管理员(避免重复插入)
cursor.execute("INSERT OR IGNORE INTO admin (username, password) VALUES (?, ?)", ("admin", "123456"))
# 2. 图书表
cursor.execute('''CREATE TABLE IF NOT EXISTS books
(book_id TEXT PRIMARY KEY,
book_name TEXT NOT NULL,
author TEXT NOT NULL,
publisher TEXT NOT NULL,
stock INTEGER NOT NULL DEFAULT 0)''')
# 3. 读者表
cursor.execute('''CREATE TABLE IF NOT EXISTS readers
(reader_id TEXT PRIMARY KEY,
reader_name TEXT NOT NULL,
phone TEXT)''')
# 4. 借阅记录表
cursor.execute('''CREATE TABLE IF NOT EXISTS borrow_records
(id INTEGER PRIMARY KEY AUTOINCREMENT,
reader_id TEXT NOT NULL,
book_id TEXT NOT NULL,
borrow_time TEXT NOT NULL,
return_time TEXT DEFAULT '未归还',
FOREIGN KEY (reader_id) REFERENCES readers(reader_id),
FOREIGN KEY (book_id) REFERENCES books(book_id))''')
conn.commit()
conn.close()
print("数据库初始化成功!")
# ===================== 数据库操作封装 =====================
def execute_sql(sql, params=()):
"""执行增/删/改 SQL 语句"""
try:
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
cursor.execute(sql, params)
conn.commit()
conn.close()
return True
except Exception as e:
messagebox.showerror("错误", f"操作失败:{str(e)}")
return False
def query_sql(sql, params=()):
"""执行查询 SQL 语句,返回结果列表"""
try:
conn = sqlite3.connect(DB_FILE)
cursor = conn.cursor()
cursor.execute(sql, params)
result = cursor.fetchall()
conn.close()
return result
except Exception as e:
messagebox.showerror("错误", f"查询失败:{str(e)}")
return []
# ===================== GUI界面与业务逻辑 =====================
class LibrarySystemUI:
def __init__(self, root):
self.root = root
# 窗口配置
self.root.title("图书管理系统 - 毕业设计版")
self.root.geometry("800x600")
self.root.resizable(False, False)
# 创建主菜单
main_menu = tk.Menu(root)
root.config(menu=main_menu)
# 菜单 - 图书管理
book_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="图书管理", menu=book_menu)
book_menu.add_command(label="图书增删改查", command=self.show_book_manage)
# 菜单 - 读者管理
reader_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="读者管理", menu=reader_menu)
reader_menu.add_command(label="读者增删查", command=self.show_reader_manage)
# 菜单 - 借阅归还
borrow_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="借阅归还", menu=borrow_menu)
borrow_menu.add_command(label="借阅/归还操作", command=self.show_borrow_return)
# 初始欢迎界面
self.show_welcome_page()
# ===================== 页面切换通用方法 =====================
def clear_frame(self):
"""清空当前窗口内容(保留菜单)"""
for widget in self.root.winfo_children():
if widget.winfo_class() != "Menu":
widget.destroy()
def show_welcome_page(self):
"""显示初始欢迎界面"""
self.clear_frame()
welcome_frame = tk.Frame(self.root)
welcome_frame.pack(fill=tk.BOTH, expand=True)
tk.Label(welcome_frame, text="图书管理系统", font=("微软雅黑", 32, "bold"), fg="#2E86AB").pack(pady=80)
tk.Label(welcome_frame, text="毕业设计专用 · Python轻量版", font=("微软雅黑", 14), fg="#7F8C8D").pack(pady=20)
tk.Label(welcome_frame, text="点击顶部菜单开始操作", font=("微软雅黑", 12), fg="#E74C3C").pack(pady=40)
# ===================== 图书管理页面 =====================
def show_book_manage(self):
self.clear_frame()
# 1. 输入区域
input_frame = tk.Frame(self.root, padx=20, pady=10)
input_frame.pack(fill=tk.X)
# 标签 + 输入框
tk.Label(input_frame, text="书号:", font=("微软雅黑", 10)).grid(row=0, column=0, padx=5, pady=5)
self.book_id = tk.Entry(input_frame, width=10)
self.book_id.grid(row=0, column=1, padx=5, pady=5)
tk.Label(input_frame, text="书名:", font=("微软雅黑", 10)).grid(row=0, column=2, padx=5, pady=5)
self.book_name = tk.Entry(input_frame, width=20)
self.book_name.grid(row=0, column=3, padx=5, pady=5)
tk.Label(input_frame, text="作者:", font=("微软雅黑", 10)).grid(row=1, column=0, padx=5, pady=5)
self.book_author = tk.Entry(input_frame, width=10)
self.book_author.grid(row=1, column=1, padx=5, pady=5)
tk.Label(input_frame, text="出版社:", font=("微软雅黑", 10)).grid(row=1, column=2, padx=5, pady=5)
self.book_pub = tk.Entry(input_frame, width=20)
self.book_pub.grid(row=1, column=3, padx=5, pady=5)
tk.Label(input_frame, text="库存:", font=("微软雅黑", 10)).grid(row=2, column=0, padx=5, pady=5)
self.book_stock = tk.Entry(input_frame, width=10)
self.book_stock.grid(row=2, column=1, padx=5, pady=5)
# 操作按钮
tk.Button(input_frame, text="添加图书", command=self.add_book, bg="#2ECC71", fg="white", width=10).grid(row=2, column=2, padx=5)
tk.Button(input_frame, text="删除图书", command=self.del_book, bg="#E74C3C", fg="white", width=10).grid(row=2, column=3, padx=5)
tk.Button(input_frame, text="修改图书", command=self.update_book, bg="#F39C12", fg="white", width=10).grid(row=2, column=4, padx=5)
tk.Button(input_frame, text="刷新列表", command=self.load_book_list, bg="#3498DB", fg="white", width=10).grid(row=2, column=5, padx=5)
# 2. 表格展示区域
table_frame = tk.Frame(self.root, padx=20, pady=10)
table_frame.pack(fill=tk.BOTH, expand=True)
# 表格配置
columns = ("book_id", "book_name", "author", "publisher", "stock")
self.book_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=15)
# 设置表头
self.book_tree.heading("book_id", text="书号")
self.book_tree.heading("book_name", text="书名")
self.book_tree.heading("author", text="作者")
self.book_tree.heading("publisher", text="出版社")
self.book_tree.heading("stock", text="库存")
# 设置列宽
self.book_tree.column("book_id", width=100)
self.book_tree.column("book_name", width=200)
self.book_tree.column("author", width=100)
self.book_tree.column("publisher", width=200)
self.book_tree.column("stock", width=80)
# 滚动条
scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.book_tree.yview)
self.book_tree.configure(yscrollcommand=scrollbar.set)
self.book_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 加载图书列表
self.load_book_list()
# 图书管理 - 加载列表
def load_book_list(self):
"""加载所有图书到表格"""
# 清空原有数据
for item in self.book_tree.get_children():
self.book_tree.delete(item)
# 查询数据
books = query_sql("SELECT * FROM books")
# 插入数据
for book in books:
self.book_tree.insert("", tk.END, values=book)
# 图书管理 - 添加
def add_book(self):
bid = self.book_id.get().strip()
bname = self.book_name.get().strip()
bau = self.book_author.get().strip()
bpub = self.book_pub.get().strip()
bstock = self.book_stock.get().strip()
if not all([bid, bname, bau, bpub, bstock]):
messagebox.showwarning("提示", "请填写所有字段!")
return
# 执行添加
sql = "INSERT INTO books (book_id, book_name, author, publisher, stock) VALUES (?, ?, ?, ?, ?)"
if execute_sql(sql, (bid, bname, bau, bpub, int(bstock))):
messagebox.showinfo("成功", "图书添加成功!")
self.load_book_list()
# 清空输入框
self.book_id.delete(0, tk.END)
self.book_name.delete(0, tk.END)
self.book_author.delete(0, tk.END)
self.book_pub.delete(0, tk.END)
self.book_stock.delete(0, tk.END)
# 图书管理 - 删除
def del_book(self):
bid = self.book_id.get().strip()
if not bid:
messagebox.showwarning("提示", "请输入要删除的书号!")
return
# 执行删除
sql = "DELETE FROM books WHERE book_id=?"
if execute_sql(sql, (bid,)):
messagebox.showinfo("成功", "图书删除成功!")
self.load_book_list()
self.book_id.delete(0, tk.END)
# 图书管理 - 修改
def update_book(self):
bid = self.book_id.get().strip()
bname = self.book_name.get().strip()
bau = self.book_author.get().strip()
bpub = self.book_pub.get().strip()
bstock = self.book_stock.get().strip()
if not bid:
messagebox.showwarning("提示", "请输入要修改的书号!")
return
# 执行修改
sql = "UPDATE books SET book_name=?, author=?, publisher=?, stock=? WHERE book_id=?"
if execute_sql(sql, (bname, bau, bpub, int(bstock), bid)):
messagebox.showinfo("成功", "图书修改成功!")
self.load_book_list()
# ===================== 读者管理页面 =====================
def show_reader_manage(self):
self.clear_frame()
# 1. 输入区域
input_frame = tk.Frame(self.root, padx=20, pady=10)
input_frame.pack(fill=tk.X)
# 标签 + 输入框
tk.Label(input_frame, text="读者ID:", font=("微软雅黑", 10)).grid(row=0, column=0, padx=5, pady=5)
self.reader_id = tk.Entry(input_frame, width=10)
self.reader_id.grid(row=0, column=1, padx=5, pady=5)
tk.Label(input_frame, text="读者姓名:", font=("微软雅黑", 10)).grid(row=0, column=2, padx=5, pady=5)
self.reader_name = tk.Entry(input_frame, width=20)
self.reader_name.grid(row=0, column=3, padx=5, pady=5)
tk.Label(input_frame, text="联系电话:", font=("微软雅黑", 10)).grid(row=1, column=0, padx=5, pady=5)
self.reader_phone = tk.Entry(input_frame, width=20)
self.reader_phone.grid(row=1, column=1, padx=5, pady=5)
# 操作按钮
tk.Button(input_frame, text="添加读者", command=self.add_reader, bg="#2ECC71", fg="white", width=10).grid(row=1, column=2, padx=5)
tk.Button(input_frame, text="删除读者", command=self.del_reader, bg="#E74C3C", fg="white", width=10).grid(row=1, column=3, padx=5)
tk.Button(input_frame, text="刷新列表", command=self.load_reader_list, bg="#3498DB", fg="white", width=10).grid(row=1, column=4, padx=5)
# 2. 表格展示区域
table_frame = tk.Frame(self.root, padx=20, pady=10)
table_frame.pack(fill=tk.BOTH, expand=True)
# 表格配置
columns = ("reader_id", "reader_name", "phone")
self.reader_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=15)
# 设置表头
self.reader_tree.heading("reader_id", text="读者ID")
self.reader_tree.heading("reader_name", text="读者姓名")
self.reader_tree.heading("phone", text="联系电话")
# 设置列宽
self.reader_tree.column("reader_id", width=150)
self.reader_tree.column("reader_name", width=200)
self.reader_tree.column("phone", width=200)
# 滚动条
scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.reader_tree.yview)
self.reader_tree.configure(yscrollcommand=scrollbar.set)
self.reader_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 加载读者列表
self.load_reader_list()
# 读者管理 - 加载列表
def load_reader_list(self):
"""加载所有读者到表格"""
# 清空原有数据
for item in self.reader_tree.get_children():
self.reader_tree.delete(item)
# 查询数据
readers = query_sql("SELECT * FROM readers")
# 插入数据
for reader in readers:
self.reader_tree.insert("", tk.END, values=reader)
# 读者管理 - 添加
def add_reader(self):
rid = self.reader_id.get().strip()
rname = self.reader_name.get().strip()
rphone = self.reader_phone.get().strip()
if not all([rid, rname, rphone]):
messagebox.showwarning("提示", "请填写所有字段!")
return
# 执行添加
sql = "INSERT INTO readers (reader_id, reader_name, phone) VALUES (?, ?, ?)"
if execute_sql(sql, (rid, rname, rphone)):
messagebox.showinfo("成功", "读者添加成功!")
self.load_reader_list()
# 清空输入框
self.reader_id.delete(0, tk.END)
self.reader_name.delete(0, tk.END)
self.reader_phone.delete(0, tk.END)
# 读者管理 - 删除
def del_reader(self):
rid = self.reader_id.get().strip()
if not rid:
messagebox.showwarning("提示", "请输入要删除的读者ID!")
return
# 执行删除
sql = "DELETE FROM readers WHERE reader_id=?"
if execute_sql(sql, (rid,)):
messagebox.showinfo("成功", "读者删除成功!")
self.load_reader_list()
self.reader_id.delete(0, tk.END)
# ===================== 借阅归还页面 =====================
def show_borrow_return(self):
self.clear_frame()
# 1. 输入区域
input_frame = tk.Frame(self.root, padx=20, pady=10)
input_frame.pack(fill=tk.X)
# 标签 + 输入框
tk.Label(input_frame, text="读者ID:", font=("微软雅黑", 10)).grid(row=0, column=0, padx=5, pady=5)
self.br_reader_id = tk.Entry(input_frame, width=10)
self.br_reader_id.grid(row=0, column=1, padx=5, pady=5)
tk.Label(input_frame, text="书号:", font=("微软雅黑", 10)).grid(row=0, column=2, padx=5, pady=5)
self.br_book_id = tk.Entry(input_frame, width=10)
self.br_book_id.grid(row=0, column=3, padx=5, pady=5)
# 操作按钮
tk.Button(input_frame, text="借阅图书", command=self.borrow_book, bg="#2ECC71", fg="white", width=10).grid(row=0, column=4, padx=5)
tk.Button(input_frame, text="归还图书", command=self.return_book, bg="#F39C12", fg="white", width=10).grid(row=0, column=5, padx=5)
tk.Button(input_frame, text="刷新记录", command=self.load_borrow_list, bg="#3498DB", fg="white", width=10).grid(row=0, column=6, padx=5)
# 2. 表格展示区域
table_frame = tk.Frame(self.root, padx=20, pady=10)
table_frame.pack(fill=tk.BOTH, expand=True)
# 表格配置
columns = ("reader_id", "book_id", "borrow_time", "return_time")
self.borrow_tree = ttk.Treeview(table_frame, columns=columns, show="headings", height=15)
# 设置表头
self.borrow_tree.heading("reader_id", text="读者ID")
self.borrow_tree.heading("book_id", text="书号")
self.borrow_tree.heading("borrow_time", text="借阅时间")
self.borrow_tree.heading("return_time", text="归还时间")
# 设置列宽
self.borrow_tree.column("reader_id", width=150)
self.borrow_tree.column("book_id", width=150)
self.borrow_tree.column("borrow_time", width=200)
self.borrow_tree.column("return_time", width=200)
# 滚动条
scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.borrow_tree.yview)
self.borrow_tree.configure(yscrollcommand=scrollbar.set)
self.borrow_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 加载借阅记录
self.load_borrow_list()
# 借阅归还 - 加载列表
def load_borrow_list(self):
"""加载所有借阅记录到表格"""
# 清空原有数据
for item in self.borrow_tree.get_children():
self.borrow_tree.delete(item)
# 查询数据
records = query_sql("SELECT reader_id, book_id, borrow_time, return_time FROM borrow_records")
# 插入数据
for record in records:
self.borrow_tree.insert("", tk.END, values=record)
# 借阅归还 - 借阅
def borrow_book(self):
rid = self.br_reader_id.get().strip()
bid = self.br_book_id.get().strip()
if not all([rid, bid]):
messagebox.showwarning("提示", "请填写读者ID和书号!")
return
# 检查读者和图书是否存在
reader_exist = query_sql("SELECT * FROM readers WHERE reader_id=?", (rid,))
book_exist = query_sql("SELECT * FROM books WHERE book_id=?", (bid,))
if not reader_exist:
messagebox.showerror("错误", "读者不存在!")
return
if not book_exist:
messagebox.showerror("错误", "图书不存在!")
return
# 生成借阅时间
borrow_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 执行借阅
sql = "INSERT INTO borrow_records (reader_id, book_id, borrow_time) VALUES (?, ?, ?)"
if execute_sql(sql, (rid, bid, borrow_time)):
messagebox.showinfo("成功", "图书借阅成功!")
self.load_borrow_list()
# 清空输入框
self.br_reader_id.delete(0, tk.END)
self.br_book_id.delete(0, tk.END)
# 借阅归还 - 归还
def return_book(self):
rid = self.br_reader_id.get().strip()
bid = self.br_book_id.get().strip()
if not all([rid, bid]):
messagebox.showwarning("提示", "请填写读者ID和书号!")
return
# 检查是否有未归还的记录
record_exist = query_sql("SELECT * FROM borrow_records WHERE reader_id=? AND book_id=? AND return_time='未归还'", (rid, bid))
if not record_exist:
messagebox.showerror("错误", "无未归还的该图书记录!")
return
# 生成归还时间
return_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 执行归还
sql = "UPDATE borrow_records SET return_time=? WHERE reader_id=? AND book_id=? AND return_time='未归还'"
if execute_sql(sql, (return_time, rid, bid)):
messagebox.showinfo("成功", "图书归还成功!")
self.load_borrow_list()
# 清空输入框
self.br_reader_id.delete(0, tk.END)
self.br_book_id.delete(0, tk.END)
# ===================== 程序入口 =====================
if __name__ == "__main__":
# 初始化数据库(首次运行自动创建)
init_database()
# 创建主窗口
root = tk.Tk()
# 启动界面
app = LibrarySystemUI(root)
# 运行主循环
root.mainloop()
更多推荐



所有评论(0)