目录
4.系统实现
1.数据库访问设计
-
数据库连接与管理
# 获取数据
self.username = self.usernameEntry.get().strip()
self.password = self.passwordEntry.get().strip()
# print(self.username)
# print(self.password)
# 打开数据库连接
db = pymysql.connect(host='localhost',
user='root',
password='Ls123456',
database='museum')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 读取数据
sql = "SELECT password FROM admins where username = %s"
cursor.execute(sql, (self.username,))
result = cursor.fetchone()
# print(result)
if result is not None:
result = result[0]
if result == self.password:
tkinter.messagebox.showinfo('通知', '管理员登录成功!')
self.destroy()
main.mainWindow()
if result is None:
sql_1 = "SELECT password FROM audience where username = %s"
cursor.execute(sql_1, (self.username,))
result_1 = cursor.fetchone()
# print(result)
if result_1 is not None:
result_1 = result_1[0]
if result_1 == self.password:
tkinter.messagebox.showinfo('通知', '登录成功!')
self.destroy()
main.mainWindow()
if result_1 is None:
isOK = tkinter.messagebox.askokcancel('通知', '用户名不存在,是否注册')
if isOK:
self.destroy()
LARPackage.register.registerWindow()
-
SQL语句查询与结果处理
query = "SELECT id, name, current_region, type, level, protection_unit FROM intangibleheritage WHERE 1=1"
if self.selected_area != "全部":
query += f" AND current_region = '{self.selected_area}'"
if self.selected_type != "全部":
query += f" AND type = '{self.selected_type}'"
if self.selected_level != "全部":
query += f" AND level = '{self.selected_level}'"
if self.selected_unit != "全部":
query += f" AND protection_unit = '{self.selected_unit}'"
# if self.Entry_query_entry is not None:
# query += f" AND name LIKE '%{self.Entry_query_entry}%'"
if self.inputEntry.get() != "项目名称" and self.inputEntry.get() is not None:
query += f" AND name LIKE '%{self.inputEntry.get()}%'"
# 连接数据库
db = pymysql.connect(host='localhost',
user='root',
password='Ls123456',
database='museum')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 执行查询
try:
cursor.execute(query)
result = cursor.fetchall()
print(result)
# 清空Treeview
self.treeview.delete(*self.treeview.get_children())
# 将查询结果填充到Treeview
for row in result:
self.treeview.insert("", "end", values=row)
except Exception as e:
print(f"查询错误:{e}")
finally:
cursor.close()
db.close()
-
SQL语句添加与结果处理
#名称
if self.nameEntry is None:
self.name = None
else:
self.name = self.nameEntry.get().strip()
#类型
if self.typeEntry is None:
self.type = None
else:
self.type = self.typeEntry.get().strip()
#等级
if self.levelEntry is None:
self.level = None
else:
self.level = self.levelEntry.get().strip()
#发源地
if self.current_regionEntry is None:
self.current_region = None
else:
self.current_region = self.current_regionEntry.get().strip()
#背景描述
if self.backgroundEntry is None:
self.background = None
else:
self.background = self.backgroundEntry.get().strip()
#保护单位
if self.protection_unitEntry is None:
self.protection_unit = None
else:
self.protection_unit = self.protection_unitEntry.get().strip()
#继承人
if self.inheritorsEntry is None:
self.inheritors = None
else:
self.inheritors = self.inheritorsEntry.get().strip()
print(self.name, self.type, self.level, self.current_region, self.background, self.protection_unit,
self.inheritors)
# print(self.username)
# print(self.password)
isOK = tkinter.messagebox.askokcancel('通知', '确认添加吗?')
if isOK:
# 打开数据库连接
db = pymysql.connect(host='localhost',
user='root',
password='Ls123456',
database='museum')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 读取数据
try:
# 构建插入数据的SQL语句
insert_sql = """
INSERT INTO intangibleheritage (
name, type, level, current_region, background, protection_unit, inheritors
) VALUES (
%s, %s, %s, %s, %s, %s, %s
)
"""
# 使用元组将数据传递给execute方法,以防止SQL注入
data_to_insert = (
self.name, self.type, self.level,
self.current_region, self.background,
self.protection_unit, self.inheritors
)
# 执行插入操作
cursor.execute(insert_sql, data_to_insert)
# 提交事务
db.commit()
tkinter.messagebox.showinfo('通知', '数据插入成功!')
print("数据插入成功!")
except pymysql.MySQLError as e:
# 如果出现错误,回滚事务
db.rollback()
tkinter.messagebox.showinfo('通知', '数据插入失败!')
print(f"数据插入失败: {e}")
finally:
# 关闭游标和数据库连接
cursor.close()
db.close()
-
SQL语句修改与结果处理
# 名称
if self.nameEntry is None:
self.name = ""
else:
self.name = self.nameEntry.get().strip()
# 类型
if self.typeEntry is None:
self.type = ""
else:
self.type = self.typeEntry.get().strip()
# 等级
if self.levelEntry is None:
self.level = ""
else:
self.level = self.levelEntry.get().strip()
# 发源地
if self.current_regionEntry is None:
self.current_region = ""
else:
self.current_region = self.current_regionEntry.get().strip()
# 背景描述
if self.backgroundEntry is None:
self.background = ""
else:
self.background = self.backgroundEntry.get().strip()
# 保护单位
if self.protection_unitEntry is None:
self.protection_unit = ""
else:
self.protection_unit = self.protection_unitEntry.get().strip()
# 继承人
if self.inheritorsEntry is None:
self.inheritors = ""
else:
self.inheritors = self.inheritorsEntry.get().strip()
print(self.name, self.type, self.level, self.current_region, self.background, self.protection_unit,
self.inheritors)
# print(self.username)
# print(self.password)
isOK = tkinter.messagebox.askokcancel('通知', '确认更新吗?')
if isOK:
# 打开数据库连接
db = pymysql.connect(host='localhost',
user='root',
password='Ls123456',
database='museum')
cursor = db.cursor()
try:
# 查询原始记录
select_sql = "SELECT * FROM intangibleheritage WHERE id = %s"
cursor.execute(select_sql, (self.id,))
fetched_record = cursor.fetchone()
# 确保查询到了记录
if fetched_record:
original_record = dict(zip(('id', 'name', 'type', 'level', 'current_region', 'background',
'protection_unit', 'inheritors'), fetched_record))
# 准备更新的数据列表,仅包含非空且与原值不同的项
update_fields = [] # 存储需要更新的字段名
update_values = [] # 存储对应的更新值
for field, new_value in [
('name', self.name),
('type', self.type),
('level', self.level),
('current_region', self.current_region),
('background', self.background),
('protection_unit', self.protection_unit),
('inheritors', self.inheritors)
]:
# 只有当新值不为空且与原值不同才添加到更新列表
if new_value and new_value != original_record[field]:
update_fields.append(field)
update_values.append(new_value)
# 添加id到列表末尾,用于WHERE条件
update_values.append(self.id)
# 构造动态的SET部分,只包括需要更新的字段
set_clause = ', '.join([f"{f} = %s" for f in update_fields])
# 构建完整的更新SQL
update_sql = f"""
UPDATE intangibleheritage
SET {set_clause}
WHERE id = %s
"""
# 执行更新操作
cursor.execute(update_sql, update_values) # 直接使用update_values
db.commit()
tkinter.messagebox.showinfo('通知', '数据更新成功!')
print("数据更新成功!")
else:
print("未找到对应的记录。")
except pymysql.MySQLError as e:
db.rollback()
tkinter.messagebox.showinfo('通知', '数据更新失败!')
print(f"数据更新失败: {e}")
finally:
cursor.close()
db.close()
-
SQL语句删除与结果处理
# 打开数据库连接
db = pymysql.connect(host='localhost',
user='root',
password='Ls123456',
database='museum')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 读取数据
sql = "SELECT username FROM admins"
cursor.execute(sql)
result = cursor.fetchall()
print(result)
for user in result:
print(user[0])
if user[0] == self.user:
delete_item = tkinter.simpledialog.askinteger("删除", "请输入需要删除传承的编号:")
if delete_item:
# print(delete_item)
isOK = tkinter.messagebox.askokcancel('通知', '确认删除吗?')
if isOK:
db = pymysql.connect(host='localhost',
user='root',
password='Ls123456',
database='museum')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
try:
# 注意:这里假设`delete_item`是要根据userName删除的,所以SQL中的占位符应该是用户名,但通常删除操作会基于ID更安全。
# 如果`delete_item`实际上是用户名,请确保这是预期的行为,否则可能需要调整为基于ID的删除逻辑。
sql_del = "DELETE FROM intangibleheritage WHERE id = %s"
# 执行删除操作,注意使用%操作符安全地插入变量到SQL语句中
cursor.execute(sql_del, (delete_item,))
# 提交到数据库执行
db.commit()
tkinter.messagebox.showinfo('通知', '数据删除成功!')
print("删除成功!")
except pymysql.MySQLError as e:
# 捕获具体的数据库错误,如权限、不存在的表或列等
print(f"数据库操作错误: {e}")
except Exception as e:
# 捕获其他所有异常
print(f"发生错误: {e}")
finally:
# 不论是否发生异常,都确保关闭游标和数据库连接
if cursor:
cursor.close()
if db:
db.close()
else:
tkinter.messagebox.showwarning("警告", "没有权限")
2.登录模块设计
def setupUI(self):
self.mainLabel = Label(text="欢迎您进入登录页面")
self.mainLabel.grid(row=0, columnspan=5)
# 用户名
self.username = Label(text='用户名:', borderwidth=3)
self.username.grid(row=1, sticky=W)
self.usernameEntry = Entry()
self.usernameEntry.grid(row=1, column=1, columnspan=3)
self.usernameEntry.focus_set()
# 密码
self.password = Label(text='密码:', borderwidth=3)
self.password.grid(row=2, sticky=W)
self.passwordEntry = Entry(show='*')
self.passwordEntry.grid(row=2, column=1, columnspan=3)
# 注册按钮
self.registerButton = Button(text='登录', borderwidth=2, command=self.login)
self.registerButton.grid(row=4, columnspan=5)
def login(self):
# 获取数据
self.username = self.usernameEntry.get().strip()
self.password = self.passwordEntry.get().strip()
# print(self.username)
# print(self.password)
# 打开数据库连接
db = pymysql.connect(host='localhost',
user='root',
password='Ls123456',
database='museum')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 读取数据
sql = "SELECT password FROM admins where username = %s"
cursor.execute(sql, (self.username,))
result = cursor.fetchone()
# print(result)
if result is not None:
result = result[0]
if result == self.password:
tkinter.messagebox.showinfo('通知', '管理员登录成功!')
self.destroy()
main.mainWindow()
if result is None:
sql_1 = "SELECT password FROM audience where username = %s"
cursor.execute(sql_1, (self.username,))
result_1 = cursor.fetchone()
# print(result)
if result_1 is not None:
result_1 = result_1[0]
if result_1 == self.password:
tkinter.messagebox.showinfo('通知', '登录成功!')
self.destroy()
main.mainWindow()
if result_1 is None:
isOK = tkinter.messagebox.askokcancel('通知', '用户名不存在,是否注册')
if isOK:
self.destroy()
LARPackage.register.registerWindow()
3.非物质文化遗产模块设计
-
界面设计
def setupUI(self):
# 风格设置
self.Style01 = Style()
self.Style01.configure("right.TPanedwindow")
self.Style01.configure("left.TPanedwindow")
# 左边:查询、TreeView
self.Pane_left = PanedWindow(width=800, height=600, style="left.TPanedwindow")
self.Pane_left.place(x=8, y=10)
# 创建一个包含查询区域和Treeview的LabelFrame,并添加边框
self.frame_container = LabelFrame(self.Pane_left, borderwidth=2, relief=GROOVE, text="查询结果", width=800,
height=600)
self.frame_container.pack(fill=BOTH, expand=True, pady=(10, 0))
# 查询区域
self.QueryFrame = Frame(self.frame_container)
self.QueryFrame.grid(row=0, column=0, sticky=NSEW, padx=10, pady=10)
# LabelFrame
self.LabelFrame_query = LabelFrame(self.QueryFrame, text="非物质文化遗产", width=700, height=70)
self.LabelFrame_query.pack(side=TOP, fill=X, padx=10, pady=10)
# 设置特定列的间隔
self.LabelFrame_query.columnconfigure(7, minsize=30) # 在第四个下拉菜单与输入框之间增加间隔
self.LabelFrame_query.columnconfigure(8, minsize=30) # 在输入框与查询按钮之间增加间隔
# 添加控件
# 地区下拉菜单
self.Label_area = Label(self.LabelFrame_query, text="地区:")
self.Label_area.grid(row=1, column=0, sticky=W)
# 定义下拉菜单的选项列表
area_options = ["全部", "北京", "上海", "天津", "重庆", "黑龙江", "辽宁", "吉林", "河北",
"河南", "湖北", "湖南", "山东", "山西", "陕西", "安徽", "浙江", "江苏",
"福建", "广东", "海南", "四川", "云南", "贵州", "青海", "甘肃", "江西",
"台湾", "内蒙古自治区", "宁夏回族自治区", "新疆维吾尔自治区", "西藏自治区", "广西壮族自治区",
"香港特别行政区", "澳门特别行政区"]
# 使用Combobox替换原来的Entry
self.ComboBox_area = Combobox(self.LabelFrame_query, values=area_options, width=9)
self.ComboBox_area.grid(row=1, column=1, sticky=W)
# 设置默认值
self.ComboBox_area.set("请选择地区") # 默认显示的文本
self.ComboBox_area.bind("<<ComboboxSelected>>", self.update_selected_area)
# 类型下拉菜单
self.Label_type = Label(self.LabelFrame_query, text="类型:")
self.Label_type.grid(row=1, column=2, sticky=W)
type_options = ["全部", "戏曲", "传统戏剧", "传统技艺", "传统体育"] # 示例选项,请根据实际情况替换
self.ComboBox_type = Combobox(self.LabelFrame_query, values=type_options, width=9)
self.ComboBox_type.grid(row=1, column=3, sticky=W)
self.ComboBox_type.set("请选择类型")
self.ComboBox_type.bind("<<ComboboxSelected>>", self.update_selected_type)
# 等级下拉菜单
self.Label_level = Label(self.LabelFrame_query, text="等级:")
self.Label_level.grid(row=1, column=4, sticky=W)
level_options = ["全部", "国家级", "世界级", "地区级"] # 示例选项,请根据实际情况替换
self.ComboBox_level = Combobox(self.LabelFrame_query, values=level_options, width=9)
self.ComboBox_level.grid(row=1, column=5, sticky=W)
self.ComboBox_level.set("请选择等级")
self.ComboBox_level.bind("<<ComboboxSelected>>", self.update_selected_level)
# 保护单位下拉菜单
self.Label_unit = Label(self.LabelFrame_query, text="保护单位:")
self.Label_unit.grid(row=1, column=6, sticky=W)
unit_options = ["全部", "中国文化和旅游部", "中国武术协会", "四川 文化和旅游厅"] # 示例选项,请根据实际情况替换
self.ComboBox_unit = Combobox(self.LabelFrame_query, values=unit_options, width=9)
self.ComboBox_unit.grid(row=1, column=7, sticky=W)
self.ComboBox_unit.set("请选择单位")
self.ComboBox_unit.bind("<<ComboboxSelected>>", self.update_selected_unit)
# 输入框
self.inputEntry = Entry(self.LabelFrame_query, width=10)
self.inputEntry.grid(row=1, column=11, sticky=W)
self.inputEntry.insert(0, "项目名称")
# 查询按钮
self.Button_query = Button(self.LabelFrame_query, text="查询", width=4, command=self.query_action)
self.Button_query.grid(row=1, column=14, sticky=W + E)
# 创建Treeview展示框
self.Treeview_frame = Frame(self.frame_container)
self.Treeview_frame.grid(row=1, column=0, sticky=NSEW, padx=10, pady=10)
# Treeview列配置
self.treeview = Treeview(self.Treeview_frame, columns=("ID", "Name", "Area", "Type", "Level", "Unit"),
show="headings")
self.treeview.heading("ID", text="ID", anchor=CENTER) # 文字居中对齐
self.treeview.heading("Name", text="名称", anchor=CENTER)
self.treeview.heading("Area", text="地区", anchor=CENTER)
self.treeview.heading("Type", text="类型", anchor=CENTER)
self.treeview.heading("Level", text="等级", anchor=CENTER)
self.treeview.heading("Unit", text="保护单位", anchor=CENTER)
# 设置列宽并居中文本
self.treeview.column("#1", stretch=NO, width=70, anchor=CENTER) # ID列宽度及居中
self.treeview.column("#2", stretch=NO, width=120, anchor=CENTER) # 名称列宽度及居中
self.treeview.column("#3", stretch=NO, width=120, anchor=CENTER) # Area列宽度及居中
self.treeview.column("#4", stretch=NO, width=120, anchor=CENTER) # Type列宽度及居中
self.treeview.column("#5", stretch=NO, width=120, anchor=CENTER) # Level列宽度及居中
self.treeview.column("#6", stretch=NO, width=130, anchor=CENTER) # Unit列宽度及居中
# 绑定滚动条
self.scrollbar = Scrollbar(self.Treeview_frame, orient=VERTICAL, command=self.treeview.yview)
self.treeview.configure(yscrollcommand=self.scrollbar.set)
self.scrollbar.pack(side=RIGHT, fill=Y)
self.treeview.pack(side=LEFT, fill=BOTH, expand=True)
# 调整查询区域和Treeview的大小
self.frame_container.grid_columnconfigure(0, weight=1)
self.frame_container.grid_rowconfigure(0, weight=1)
self.QueryFrame.grid_columnconfigure(0, weight=1)
self.Treeview_frame.grid_columnconfigure(0, weight=1)
# 按钮区域
self.ButtonFrame = Frame(self.Pane_left)
self.ButtonFrame.pack(fill=X, pady=10)
# 设置ButtonFrame的列配置,使得按钮之间有相等的间隔
for i in range(4): # 假设一共有4个按钮
self.ButtonFrame.columnconfigure(i, weight=1, uniform="equal") # uniform确保各列间距相等
# 右边:按钮区域
self.Button_add = Button(self.ButtonFrame, text="添加", command=self.add)
self.Button_add.grid(row=0, column=0, padx=5, pady=5, sticky=W + E)
self.Button_update = Button(self.ButtonFrame, text="修改", command=self.modify)
self.Button_update.grid(row=0, column=1, padx=5, pady=5, sticky=W + E)
self.Button_delete = Button(self.ButtonFrame, text="删除", command=self.delete)
self.Button_delete.grid(row=0, column=2, padx=5, pady=5, sticky=W + E)
self.Button_modify = Button(self.ButtonFrame, text="返回主界面", command=self.backMain)
self.Button_modify.grid(row=0, column=3, padx=5, pady=5, sticky=W + E)
-
图片(内容未证实)
4.系统主模块设计
-
界面代码
class mainWindow(Tk):
def __init__(self):
super().__init__()
self.title("文化传承博物馆系统")
# 设置窗口大小并禁用调整大小
self.resizable(False, False)
# 获取屏幕宽度和高度
screen_width = self.winfo_screenwidth()
screen_height = self.winfo_screenheight()
# 计算窗口在屏幕中央的位置
window_width = 1090
window_height = 585
x_pos = (screen_width - window_width) // 2
y_pos = (screen_height - window_height) // 2
# 设置窗口大小和位置
self.geometry(f"{window_width}x{window_height}+{x_pos}+{y_pos}")
# 调用设置界面方法
self.setupUI()
def setupUI(self):
# 创建主菜单
self.menu = Menu(self)
self.config(menu=self.menu)
# 添加“个人中心”菜单及子项
self.person_menu = Menu(self.menu, tearoff=0)
self.person_menu.add_command(label="用户详情", command=self.details)
self.person_menu.add_separator()
self.person_menu.add_command(label="退出系统", command=self.quit)
self.menu.add_cascade(label="个人中心", menu=self.person_menu)
# 添加“学者”菜单及子项
self.scholar_menu = Menu(self.menu, tearoff=0)
self.scholar_menu.add_command(label="专家", command=self.experts)
self.scholar_menu.add_command(label="继承人", command=self.inheritors)
self.menu.add_cascade(label="学者", menu=self.scholar_menu)
# 添加“内容”菜单及子项
self.content_menu = Menu(self.menu, tearoff=0)
self.content_menu.add_command(label="非物质文化遗产", command=self.ich)
self.content_menu.add_command(label="物质文化遗产", command=self.tch)
self.menu.add_cascade(label="内容", menu=self.content_menu)
# 添加“帮助”菜单及子项
self.help_menu = Menu(self.menu, tearoff=0)
self.help_menu.add_command(label="关于", command=self.about)
self.menu.add_cascade(label="帮助", menu=self.help_menu)
self.Style01 = Style()
self.Style01.configure("right.TPanedwindow")
self.Style01.configure("left.TPanedwindow")
self.Style01.configure("TButton", width=10)
# Top_banner
self.Lable_text = Label(text="欢迎使用文化遗产博物馆系统", font=("微软雅黑", 20))
self.Lable_text.config(anchor=CENTER, justify=CENTER)
self.Lable_text.pack()
# 在此处添加图片
image_path = "./img/2.jpeg" # 请替换为您的图片路径
image = Image.open(image_path)
photo = ImageTk.PhotoImage(image)
self.image_label = Label(self, image=photo)
self.image_label.image = photo # 保持对图片的引用,防止被垃圾回收器回收
self.image_label.pack()
def ich(self):
self.destroy()
ichPackage.ich.ichWindow()
def tch(self):
self.destroy()
tch.tchWindow()
def experts(self):
self.destroy()
expertPackage.expert.expertWindow()
def inheritors(self):
self.destroy()
inheritorsPackage.inheritors.inheritorsWindow()
def details(self):
self.destroy()
userPackage.details.detailsWindow()
def about(self):
tkinter.messagebox.showinfo('系统简介', '随着信息技术的飞速发展,互联网已经成为人们获取知识和信息的重要渠道。'
'为了应对全球范围内工业化和现代化进程中对传统文化造成的冲击和破坏。'
'在全球化和数字化的时代背景下,'
'文化遗产保护与传承面临着新的机遇与挑战。为了更好地保护、传播和利用文化遗产资源,文化遗产博物馆系统应运而生。')
-
图片(难以完全表达主题)
5.系统测试
-
查询
-
删除
-
添加
-
修改
6. 代码链接
链接:https://pan.baidu.com/s/1tituxPWldGkVCbJXb2XJJQ
提取码:te1g