Compare commits

...

2 Commits

@ -0,0 +1,17 @@
import tkinter.font as tkFont
import tkinter
from tkinter import *
from tkinter import ttk, messagebox
import pymysql
class BaseWindow(Frame):
def __init__(self, master, attr):
super().__init__(master)
self.attr = attr
self.master = master
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
# self.conn = pymysql.connect(user="root", password="123123", database="stu_sys", host="127.0.0.1", port=3306)

@ -0,0 +1,17 @@
import pymysql
if __name__ == '__main__':
# 建立数据库连接的语句connection
connection = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
cursor = connection.cursor() # 创建游标
sql = "select * from student" # SQL语句字符串
# 为了防止SQL注入等安全问题可以使用参数化查询。
try:
cursor.execute(sql) # 执行SQL语句
ResultList = cursor.fetchall() # 获取游标中的数据
print(ResultList) # Student[(S#,Sname,Sage,...),...]
except pymysql.Error as e: # 捕获报错信息
print("MySQL Error:", e) # 打印报错信息
finally:
cursor.close() # 关闭游标
connection.close() # 关闭数据库连接

@ -1,2 +1 @@
# DatabaseThinkingandRelationalDatabase # DatabaseThinkingandRelationalDatabase

@ -0,0 +1,57 @@
import pymysql
def create_database(conn):
cursor = conn.cursor() # 创建游标
cursor.execute("DROP DATABASE IF EXISTS SCT")
# 创建数据库
cursor.execute("CREATE DATABASE SCT CHARACTER SET utf8 COLLATE utf8_general_ci")
cursor.close() # 关闭游标
def create_table(conn):
cursor = conn.cursor() # 创建游标
cursor.execute("USE SCT") # 指定数据库
# 创建student数据表
cursor.execute("""
CREATE TABLE IF NOT EXISTS student
(
sid CHAR(8) PRIMARY KEY,
sname CHAR(10),
ssex CHAR(2),
sage INTEGER,
sclass CHAR(6)
)
""")
# 创建Course数据表
cursor.execute("""
CREATE TABLE IF NOT EXISTS course
(
cid CHAR(4) PRIMARY KEY,
cname CHAR(30),
credit FLOAT(1),
chours INTEGER,
t CHAR(3)
)
""")
# 创建SC数据表
cursor.execute("""
CREATE TABLE IF NOT EXISTS sc
(
sid CHAR(8),
cid CHAR(4),
score FLOAT(1),
CONSTRAINT sc_course_cid_fk
FOREIGN KEY (cid) REFERENCES course (cid),
CONSTRAINT sc_student_sid_fk
FOREIGN KEY (sid) REFERENCES student (sid)
)
""")
cursor.close()
if __name__ == '__main__':
# conn = pymysql.connect(user="root", password="123456", database="SCT", host="127.0.0.1", port=3306)
conn = pymysql.connect(user="root", password="Wyz010810", host="127.0.0.1", port=3306)
create_database(conn)
create_table(conn)
conn.close() # 关闭数据库连接

@ -0,0 +1,86 @@
# encoding: utf8
import time
import pymysql
import random
last_names = "李,王,张,刘,陈,杨,黄,赵,周,吴,徐,孙,朱,马,胡,郭,林,何,高,梁,郑,罗,宋,谢,唐,韩,曹,许,邓,萧,冯,曾,程,蔡,彭,潘,袁,于,董,余,苏,叶,吕,魏,蒋,田,杜,丁,沈,姜,范,江,傅,钟,卢,汪,戴,崔,任,陆,廖,姚,方,金,邱,夏,谭,韦,贾,邹,石,熊,孟,秦,阎,薛,侯,雷,白,龙,段,郝,孔,邵,史,毛,常,万,顾,赖,武,康,贺,严,尹,钱,施,牛,洪,龚"
last_names_list = last_names.split("")
course_names = "语文、数学、外语、历史、思想政治、地理、 化学、物理、生物、体育、美术、音乐、技术、微积分、体育、毛泽东思想概论、思想道德修养、高等数学、线性代数、概率论与数理统计、离散数学、计算机原理、人工智能、程序设计基础、面向对象程序设计、数字逻辑电路、电路电子技术、数据结构与算法、WEB程序设计、计算机组成与结构、操作系统、数据库系统原理、编译原理、计算机网络"
course_names_list = course_names.split("")
# 随机生成10000条学生表数据
def student_random_record(conn, cursor):
"""
# 随机生成10000条学生表数据
:return:
"""
year = time.localtime().tm_year # 获取当前系统时间的年份
num = 1
class_num = 1
class_id = 1
for i in range(10000):
sid = "%d" % year + "%04d" % num
sname = random.choice(last_names_list) + sid
ssex = random.choice(["", ""])
sage = random.randint(15, 35)
sclass = "%d" % year + "%02d" % class_id
sql = f"INSERT INTO student VALUES ('{sid}', '{sname}', '{ssex}', {sage}, '{sclass}')"
cursor.execute(sql)
sid_list.append(sid)
if num == 2500: # 每年学生数2500
year += 1
num = 1
class_id = 1
if class_num == 30: # 班级学生数30
class_id += 1
class_num = 1
num += 1
class_num += 1
conn.commit()
def course_random_record(conn, cursor):
"""
随机生成1000条课程表数据
:return:
"""
hours = [i for i in range(8, 192 + 1, 8)]
for i in range(1000):
cid = "%03d" % (i + 1)
cname = random.choice(course_names_list)# course_names_list为样例课程名列表
hour = random.choice(hours)
credit = round(hour / 16, 2)
sql = f"INSERT INTO course (cid, cname, credit, chours) VALUES ('{cid}', '{cname}', {credit}, {hour})"
cursor.execute(sql)
cid_list.append(cid)
conn.commit()
def sc_random_record(conn, cursor):
"""
随机生成10000 * 30条以上选课表数据
:return:
"""
for sid in sid_list:
year = int(sid[:4]) # 取sid的前四位学年
for i in range((year - time.localtime().tm_year + 1) * 16): # 学习课程按学年有16、32、48、64门按学年递增分布
cid = random.choice(cid_list)
score = random.randint(0, 101)
sql = f"INSERT INTO sc(sid, cid, score) VALUES ('{sid}', '{cid}', {score})"
cursor.execute(sql)
conn.commit()
if __name__ == '__main__':
# 创建mysql连接
conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
# 创建游标
cursor = conn.cursor()
sid_list = [] # 用于存储生成的sid
cid_list = [] # 用于存储生成的cid
student_random_record(conn, cursor)
course_random_record(conn, cursor)
sc_random_record(conn, cursor)
# 关闭数据库连接
cursor.close()
conn.close()

@ -0,0 +1,31 @@
import pymysql
# 创建mysql连接连接并打开数据库
conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
cursor = conn.cursor() # 游标的定义、打开
# 字符串型SQL语句的执行
SQLString = "INSERT INTO student VALUES ('20220001', '张三', '', 20, '01')"
cursor.execute(SQLString)
SQLString = "INSERT INTO course VALUES ('1001', '数据库', 3, 48, 'T01')"
cursor.execute(SQLString)
SQLString = "INSERT INTO sc VALUES ('20230001', '1001', 85)"
cursor.execute(SQLString)
conn.commit()
def query_data(table_name):
"""
游标数据的读写处理读写游标数据
:param table_name: 表名称
:return: 游标数据
"""
SQLString = f"SELECT * FROM {table_name}"
cursor.execute(SQLString) # 执行查询sql语句
data = cursor.fetchall() # 获取游标中的数据
return data
StudentList = query_data("student")
CourseList = query_data("course")
SCList = query_data("sc")
# 关闭数据库连接
cursor.close()
conn.close()

@ -0,0 +1,214 @@
from tkinter import Frame
import tkinter.font as tkFont
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from ttkbootstrap.tableview import Tableview
from BaseWindow import BaseWindow
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
class LoadElement(Frame):
def __init__(self, master, table_name):
super().__init__(master)
self.master = master
self.table_name = table_name
self.TableList = pd.read_sql(f"select * from {self.table_name} limit 0", conn)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.create_widget()
self.create_tree_widget()
def create_widget(self):
# 创建装载按钮
label = Label(self, width=10, font=self.font_style, text=self.table_name, style="inverse-secondary")
label.grid(column=0, row=0)
Button(self, text="装载", width=10, command=self.load).grid(column=1, row=0, padx=5, sticky=NSEW)
def create_tree_widget(self):
frame = Frame(self, width=50, height=220)
frame.grid(row=1, column=0, columnspan=2, sticky=NSEW, pady=5)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = self.TableList.keys().tolist()
style = ttk.Style()
style.configure("Custom.Treeview.Heading", font=("宋体", 15))
style.configure("Custom.Treeview", rowheight=30, font=("宋体", 15))
tree = ttk.Treeview(frame, columns=columns, show="headings", style="Custom.Treeview", selectmode=BROWSE)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, width=80)
if columns.index(i) == 1 or columns.index(i) == 0:
tree.column(i, anchor=CENTER, width=120)
for row in self.TableList.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
y_scrollbar = ttk.Scrollbar(self, orient='vertical', command=tree.yview)
x_scrollbar = ttk.Scrollbar(frame, orient="horizontal", command=tree.xview)
tree.configure(yscrollcommand=y_scrollbar.set)
tree.config(height=6)
tree.grid(row=0, column=0, columnspan=2, sticky=NSEW, pady=5)
y_scrollbar.grid(row=1, column=3, sticky='ns')
x_scrollbar.grid(row=2, column=0, columnspan=2, sticky='ew')
frame.grid_propagate(False)
def load(self):
"""
加载数据
:return:
"""
SQLString = f"select * from {self.table_name}"
# 执行SQL语句 并返回列表数据
self.TableList = pd.read_sql(SQLString, conn)
# 调用X2界面函数将self.TableList数据展示出来
self.create_tree_widget()
class FormElement(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.default_query_sql = "select * from student"
self.create_form()
fields_mapping = {'sid': '学号', 'sname': '姓名', 'ssex': '性别', 'sage': '年龄', 'sclass': '班级'}
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn), fields_mapping)
def create_form(self):
# 创建表单区域
self.sql_text = Text(self, width=75, height=4, font=self.font_style)
self.sql_text.grid(row=0, column=0, rowspan=2)
Button(self, text="\n\n执行SQL\n\n", command=self.execute_sql, width=7, style=INFO, compound=TOP).grid(column=1, row=0, rowspan=2, padx=10)
self.sql_text.insert(1.0, self.default_query_sql)
def execute_sql(self):
"""
执行sql方法
:return:
"""
# 获取text组件中用户输入的值
sql = get_text_content(self.sql_text).lower().strip()
print(sql)
def create_treeview(self, data_frame,fields_mapping):
"""
创建数据列表展示组件
:param data_frame:
:return:
"""
frame = Frame(self, height=700) # 创建一个 Frame (框架) 组件,作为树形视图的容器
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW)
# 这两行代码使得框架内的行和列可以随着窗口大小的改变而伸缩。
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
# columns = data_frame.keys().tolist()
# 使用字段名映射将列名转换为中文
columns = [fields_mapping.get(col, col) for col in data_frame.keys().tolist()]
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50,
selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns: # 通过循环,为每一列设置标题(列名)
tree.heading(column=i, text=i)
for i in columns: # 通过循环,为每一列设置列宽
tree.column(i, anchor=CENTER, minwidth=100, width=100)
for row in data_frame.itertuples(): # 循环遍历 DataFrame 的每一行,并将数据插入到树形视图中
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview) # 创建一个垂直滚动条,并将其与树形视图的垂直滚动事件绑定
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False) # 禁止框架自动调整其大小以适应其中的内容
class StuSys_X2(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
def create_left_plate(self):
# 创建左侧装载区域的组件
self.left_frame = Frame(self.master, height=self.attr["height"])
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "sc")
load_element2.pack(side=TOP, pady=10)
def create_right_plate(self):
# 创建右侧表单以及数据展示的组件
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
form_element = FormElement(self.right_frame)
form_element.pack(side=TOP, pady=10, anchor=NE)
# if __name__ == '__main__':
# """
# minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
# cyborg, vapor, simplex, cerculean,
# """
# style = "morph"
# root = Window(themename=style)
# screenwidth = root.winfo_screenwidth()
# screenheight = root.winfo_screenheight()
# root.columnconfigure(0, weight=1)
# root.rowconfigure(1, weight=1)
# root_attr = {
# "width": screenwidth * 0.83,
# "height": screenheight * 0.85,
# }
# alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
# (screenheight - root_attr['height']) / 2)
# root.geometry(alignstr)
# root.resizable(width=False, height=False)
# app = StuSys_X2(root, root_attr)
#
# ttk.Style().configure("TButton", font="-size 18")
# root.mainloop()
if __name__ == '__main__':
"""
minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
cyborg, vapor, simplex, cerculean,
"""
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
# "width": screenwidth * 0.83,
# "height": screenheight * 0.85,
"width": screenwidth * 0.61,
"height": screenheight * 0.63,
}
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
app = StuSys_X2(root, root_attr)
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

@ -0,0 +1,129 @@
from tkinter import Frame
import tkinter.font as tkFont
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from ttkbootstrap.toast import ToastNotification
from BaseWindow import BaseWindow
from X2.StuSys_X2_bootstrap import LoadElement
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
class FormElement(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.default_query_sql = "select * from student"
self.create_form()
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn))
def create_form(self):
# 创建表单区域
self.sql_text = Text(self, width=75, height=6, font=self.font_style)
self.sql_text.grid(row=0, column=0, rowspan=2)
Button(self, text="\n\n执行SQL\n\n", command=self.execute_sql, width=8,
).grid(column=1, row=0, rowspan=2, padx=10)
self.sql_text.insert(1.0, self.default_query_sql)
def sql_query(self, SQLString):
SQLResultList = pd.read_sql(SQLString, self.conn)
return SQLResultList
def execute_sql(self):
# 执行sql并将sql执行后查询的数据展示
sql = get_text_content(self.sql_text).lower().strip()
if sql.startswith("select"):
data_frame = self.sql_query(sql)
self.create_treeview(data_frame)
ToastNotification(message="语句执行成功",
title="提示",
duration=1500,
position=(int(self.winfo_screenwidth() / 2) - 150, 80, "ne"),
bootstyle="success",
icon="").show_toast()
def create_treeview(self, data_frame):
frame = Frame(self, height=700)
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = data_frame.keys().tolist()
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50,
selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, minwidth=100, width=100)
for row in data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview)
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False)
class StuSys_X3(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
def create_left_plate(self):
self.left_frame = Frame(self.master, height=self.attr["height"])
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "sc")
load_element2.pack(side=TOP, pady=10)
def create_right_plate(self):
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
form_element = FormElement(self.right_frame)
form_element.pack(side=TOP, pady=10, anchor=NE)
if __name__ == '__main__':
"""
minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
cyborg, vapor, simplex, cerculean,
"""
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
"width": screenwidth * 0.83,
"height": screenheight * 0.85,
}
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
app = StuSys_X3(root, root_attr)
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

@ -0,0 +1,199 @@
from tkinter import Frame
import tkinter.font as tkFont
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from ttkbootstrap.toast import ToastNotification
from BaseWindow import BaseWindow
from X2.StuSys_X2_bootstrap import LoadElement
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
class FormElement(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.default_query_sql = "select * from student"
self.create_form()
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn))
def create_form(self):
"""
创建表单
:return:
"""
self.sid_var = IntVar()# 学号
self.sname_var = IntVar()# 姓名
self.sclass_var = IntVar()# 班级
self.ssex_var = IntVar()# 性别
self.sage_var = IntVar()# 年龄
Label(self, text="学号", font=self.font_style).grid(row=0, column=0, sticky=W)
# 创建复选框,表示选择条件的选择状态,并将变量进行关联
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sid_var).grid(row=0, column=1, sticky=W)
self.sid = Entry(self, width=20, font=self.font_style) # 条件输入文本框
self.sid.grid(row=0, column=2, sticky=W)
# ... 其他字段部分的创建类似,以下省略
Label(self, text="姓名", font=self.font_style).grid(row=0, column=3, sticky=W)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sname_var).grid(row=0, column=4, sticky=W)
self.sname = Entry(self, width=20, font=self.font_style) # 选择条件文本框
self.sname.grid(row=0, column=5, sticky=W)
Label(self, text="班级", font=self.font_style).grid(row=1, column=0, sticky=W)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sclass_var).grid(row=1, column=1, sticky=W)
self.sclass = Entry(self, width=20, font=self.font_style)
self.sclass.grid(row=1, column=2, sticky=W)
Label(self, text="性别", font=self.font_style).grid(row=1, column=3, sticky=W)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.ssex_var).grid(row=1, column=4, sticky=W)
self.ssex = Entry(self, width=20, font=self.font_style)
self.ssex.grid(row=1, column=5, sticky=W, pady=10)
Label(self, text="年龄自", font=self.font_style).grid(row=2, column=0, sticky=W)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sage_var).grid(row=2, column=1, sticky=W)
self.start_age = Entry(self, width=20, font=self.font_style)
self.start_age.grid(row=2, column=2, sticky=W)
Label(self, text="", font=self.font_style).grid(row=2, column=3, sticky=W)
Label(self, text="", font=self.font_style).grid(row=2, column=4, sticky=W)
self.end_age = Entry(self, width=20, font=self.font_style)
self.end_age.grid(row=2, column=5, sticky=W, pady=10)
Button(self, text="\n\n构造SQL\n\n", command=self.make_sql, width=8,
).grid(column=8, row=0, rowspan=3)
self.sql_text = Text(self, height=3, font=self.font_style, width=75)
self.sql_text.grid(row=4, column=0, rowspan=2, columnspan=7, sticky=W)
Button(self, text="\n执行SQL\n", command=self.execute_sql, width=8,
).grid(column=8, row=4, rowspan=2, padx=10)
self.sql_text.insert(1.0, self.default_query_sql)
def execute_sql(self):
sql = get_text_content(self.sql_text).lower().strip()
if sql.startswith("select"):
data_frame = pd.read_sql(sql, con=self.conn)
self.create_treeview(data_frame)
ToastNotification(message="语句执行成功",
title="提示",
duration=1500,
position=(int(self.winfo_screenwidth() / 2) - 150, 80, "ne"),
bootstyle="success",
icon="").show_toast()
#""
def create_treeview(self, data_frame):
frame = Frame(self, height=600)
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = data_frame.keys().tolist()
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50,
selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, minwidth=100, width=100)
for row in data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview)
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False)
def make_sql(self):
"""
获取用户输入进行条件判断进行SQLString的构造
:return:
"""
# 根据表单条件生成sql语句
SQLString = "select * from student where 1=1"
if self.sid.get() != "":
SQLString += f" and (sid like '{self.sid.get()}')"
if self.sname.get() != "":
SQLString += f" and (sname like '{self.sname.get()}')"
if self.sclass.get() != "":
SQLString += f" and (sclass like '{self.sclass.get()}')"
if self.ssex.get() != "":
SQLString += f" and (ssex like '{self.ssex.get()}')"
if self.start_age.get() != "":
SQLString += f" and (sage > '{self.start_age.get()}')"
if self.end_age.get() != "":
SQLString += f" and (sage < '{self.end_age.get()}')"
if SQLString == "select * from student where 1=1":
SQLString = "select * from student"
SQLString = SQLString.replace("1=1 and", "")
if (self.sid_var and self.ssex_var and self.sage_var and self.sclass_var and self.sname_var == 0):
pass
else:
data = []
data.append("sid")if self.sid_var.get() == 1 else ""
data.append("sname")if self.sname_var.get() == 1 else ""
data.append("ssex")if self.ssex_var.get() == 1 else ""
data.append("sage")if self.sage_var.get() == 1 else ""
data.append("sclass")if self.sclass_var.get() == 1 else ""
SQLString = SQLString.replace("select *", f"select {', '.join(data)} ")
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, SQLString)
class StuSys_X4(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
def create_left_plate(self):
self.left_frame = Frame(self.master, height=self.attr["height"])
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "sc")
load_element2.pack(side=TOP, pady=10)
def create_right_plate(self):
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10, fill=BOTH)
form_element = FormElement(self.right_frame)
form_element.pack(side=TOP, pady=10, anchor=NE, fill=BOTH)
if __name__ == '__main__':
"""
minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
cyborg, vapor, simplex, cerculean,
"""
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
"width": screenwidth * 0.83,
"height": screenheight * 0.85,
}
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
app = StuSys_X4(root, root_attr)
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

@ -0,0 +1,248 @@
from tkinter import Frame
import tkinter.font as tkFont
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from ttkbootstrap.toast import ToastNotification
from BaseWindow import BaseWindow
from X2.StuSys_X2_bootstrap import LoadElement
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
class FormElement(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.default_query_sql = "select * from student"
self.create_form()
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn))
def create_form(self):
self.sid_var = IntVar()#学号
self.sname_var = IntVar()#姓名
self.sclass_var = IntVar()#班级
self.ssex_var = IntVar()#性别
self.sage_var = IntVar()#年龄自
self.score_var = IntVar()#成绩大于
self.courseId_var = IntVar()#课号
self.cname_var = IntVar()#课名
self.credit_var = IntVar()
self.chours_var = IntVar()
# 表明标签:学生/student
Label(self, text="学生/student", font=("Lucida Grande", 20), style="inverse").grid(row=0, column=0, sticky=W)
# 学号标签
Label(self, text="学号", font=self.font_style).grid(row=1, column=0, sticky=E)
# 创建复选框,表示选择条件的选择状态,并将变量进行关联
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sid_var).grid(row=1, column=1, sticky=W)
# 选择条件文本框
self.sid = Entry(self, width=20, font=self.font_style)
self.sid.grid(row=1, column=2, sticky=W)
# ...其他字段部分的创建类似,以下省略
# 姓名
Label(self, text="姓名", font=self.font_style).grid(row=1, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sname_var).grid(row=1, column=4, sticky=W)
self.sname = Entry(self, width=20, font=self.font_style)
self.sname.grid(row=1, column=5, sticky=W)
Label(self, text="班级", font=self.font_style).grid(row=2, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sclass_var).grid(row=2, column=1, sticky=W)
self.sclass = Entry(self, width=20, font=self.font_style)
self.sclass.grid(row=2, column=2, sticky=W)
Label(self, text="性别", font=self.font_style).grid(row=2, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.ssex_var).grid(row=2, column=4, sticky=W)
self.ssex = Entry(self, width=20, font=self.font_style)
self.ssex.grid(row=2, column=5, sticky=W, pady=10)
Label(self, text="年龄自", font=self.font_style).grid(row=3, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sage_var).grid(row=3, column=1, sticky=W)
self.start_age = Entry(self, width=20, font=self.font_style)
self.start_age.grid(row=3, column=2, sticky=W)
Label(self, text="", font=self.font_style).grid(row=3, column=3, sticky=E)
Label(self, text="", font=self.font_style).grid(row=3, column=4, sticky=W)
self.end_age = Entry(self, width=20, font=self.font_style)
self.end_age.grid(row=3, column=5, sticky=W, pady=10)
Label(self, text="课程/course", font=("Lucida Grande", 20), style="inverse").grid(row=4, column=0, sticky=W)
Label(self, text="课号", font=self.font_style).grid(row=5, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.courseId_var).grid(row=5, column=1, sticky=W)
self.course_id = Entry(self, width=20, font=self.font_style)
self.course_id.grid(row=5, column=2, sticky=W)
Label(self, text="课名", font=self.font_style).grid(row=5, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.cname_var).grid(row=5, column=4, sticky=W)
self.course_name = Entry(self, width=20, font=self.font_style)
self.course_name.grid(row=5, column=5, sticky=W, pady=10)
Label(self, text="选课/sc", font=("Lucida Grande", 20), style="inverse").grid(row=6, column=0, sticky=W)
Label(self, text="成绩大于", font=self.font_style).grid(row=7, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.score_var).grid(row=7, column=1, sticky=W)
self.sc_start = Entry(self, width=20, font=self.font_style)
self.sc_start.grid(row=7, column=2, sticky=W)
Label(self, text="小于", font=self.font_style).grid(row=7, column=3, sticky=E)
Label(self, text="", font=self.font_style).grid(row=7, column=4, sticky=W)
self.sc_end = Entry(self, width=20, font=self.font_style)
self.sc_end.grid(row=7, column=5, sticky=W, pady=10)
# 配置并创建一个"构造SQL"按钮
Button(self, text="\n\n构造SQL\n\n", command=self.make_sql, width=8,
).grid(column=8, row=0, rowspan=8)
# 创建一个"执行SQL"按钮用于执行文本框中的SQL命令
self.sql_text = Text(self, height=3, font=self.font_style, width=75)
self.sql_text.grid(row=8, column=0, rowspan=2, columnspan=7, sticky=W)
Button(self, text="\n执行SQL\n", command=self.execute_sql, width=8,
).grid(column=8, row=8, rowspan=2, padx=10)
# 插入默认的查询SQL
self.sql_text.insert(1.0, self.default_query_sql)
def execute_sql(self):
sql = get_text_content(self.sql_text).lower().strip()
if sql.startswith("select"):
data_frame = pd.read_sql(sql, con=self.conn)
self.create_treeview(data_frame)
ToastNotification(message="语句执行成功",
title="提示",
duration=1500,
position=(int(self.winfo_screenwidth() / 2) - 150, 80, "ne"),
bootstyle="success",
icon="").show_toast()
def create_treeview(self, data_frame):
frame = Frame(self, height=400)
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = data_frame.keys().tolist()
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50,
selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, minwidth=100, width=100)
for row in data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview)
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False)
def make_sql(self):
sql = "select * from student where 1=1"
if self.course_id and self.course_name and self.sc_start and self.sc_end != "":
# 如果条件满足则调整SQL查询以包含多个表
sql = "select * from student s join sc on sc.sid=s.sid join course c on c.cid=sc.cid"
if self.sid.get() != "":
sql += f" and (s.sid like '{self.sid.get()}')"
if self.sname.get() != "":
sql += f" and (s.sname like '{self.sname.get()}')"
if self.sclass.get() != "":
sql += f" and (s.sclass like '{self.sclass.get()}')"
if self.ssex.get() != "":
sql += f" and (s.ssex like '{self.ssex.get()}')"
if self.start_age.get() != "":
sql += f" and (s.sage > '{self.start_age.get()}')"
if self.end_age.get() != "":
sql += f" and (s.sage < '{self.end_age.get()}')"
if self.course_id.get() != "":
sql += f" and (c.cid like '{self.course_id.get()}')"
if self.course_name.get() != "":
sql += f" and (c.cname like '{self.course_name.get()}')"
if self.sc_start.get() != "":
sql += f" and (sc.score > {self.sc_start.get()})"
if self.sc_end.get() != "":
sql += f" and (sc.score < {self.sc_end.get()})"
else:
if self.sid.get() != "":
sql += f" and (sid like '{self.sid.get()}')"
if self.sname.get() != "":
sql += f" and (sname like '{self.sname.get()}')"
if self.sclass.get() != "":
sql += f" and (sclass like '{self.sclass.get()}')"
if self.start_age.get() != "":
sql += f" and (sage > '{self.start_age.get()}')"
if self.end_age.get() != "":
sql += f" and (sage < '{self.end_age.get()}')"
if sql == "select * from student where 1=1":
sql = "select * from student"
if (self.sid_var and self.ssex_var and self.sage_var and self.sclass_var and self.sname_var and self.score_var and self.cname_var and self.credit_var and self.chours_var == 0):
pass
else:
data = []
data.append("s.sid")if self.sid_var.get() == 1 else ""
data.append("s.sname")if self.sname_var.get() == 1 else ""
data.append("s.ssex")if self.ssex_var.get() == 1 else ""
data.append("s.sage")if self.sage_var.get() == 1 else ""
data.append("s.sclass")if self.sclass_var.get() == 1 else ""
data.append("sc.score")if self.score_var.get() == 1 else ""
data.append("c.cid")if self.courseId_var.get() == 1 else ""
data.append("c.cname")if self.cname_var.get() == 1 else ""
data.append("c.credit")if self.credit_var.get() == 1 else ""
data.append("c.chours")if self.chours_var.get() == 1 else ""
sql = sql.replace("select *", f"select {', '.join(data)} ")
sql = sql.replace("1=1 and", "")# 如果查询条件未改变,则简化查询语句,移除字符串中无用的部分
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, sql)# 插入新构造的SQL查询字符串
class StuSys_X4(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
def create_left_plate(self):
self.left_frame = Frame(self.master, height=self.attr["height"])
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "sc")
load_element2.pack(side=TOP, pady=10)
def create_right_plate(self):
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
form_element = FormElement(self.right_frame)
form_element.pack(side=TOP, pady=10, anchor=NE)
if __name__ == '__main__':
"""
minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
cyborg, vapor, simplex, cerculean,
"""
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
"width": screenwidth * 0.83,
"height": screenheight * 0.85,
}
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
app = StuSys_X4(root, root_attr)
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

@ -0,0 +1,301 @@
from tkinter import Frame
import tkinter.font as tkFont
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from ttkbootstrap.toast import ToastNotification
from BaseWindow import BaseWindow
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
class LoadElement(Frame):
def __init__(self, master, table_name):
super().__init__(master)
self.master = master
self.table_name = table_name
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.data_frame = pd.read_sql(f"select * from {self.table_name} limit 0", self.conn)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.create_widget()
self.select_value(None)
self.create_tree_widget()
def select_value(self, event):
self.table_name = self.select_stringVar.get()
def create_widget(self):
data_frame = pd.read_sql("show tables", self.conn)
tables = [i[0] for i in data_frame.values.tolist()]
style = ttk.Style()
self.select_stringVar = StringVar()
self.select_stringVar.set(self.table_name)
combo = ttk.Combobox(self, width=10, textvariable=self.select_stringVar,font=self.font_style, style="TCombobox")
combo["values"] = tables
combo.bind('<<ComboboxSelected>>', self.select_value)
combo.grid(column=0, row=0)
Button(self, text="装载", width=10, command=self.load).grid(column=1, row=0, padx=5)
def create_tree_widget(self):
frame = Frame(self, width=50, height=220)
frame.grid(row=1, column=0, columnspan=2, sticky=NSEW, pady=5)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = self.data_frame.keys().tolist()
style = ttk.Style()
style.configure("Custom.Treeview.Heading", font=("宋体", 15))
style.configure("Custom.Treeview", rowheight=30, font=("宋体", 15))
tree = ttk.Treeview(frame, columns=columns, show="headings", style="Custom.Treeview", selectmode=BROWSE)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, width=80)
if columns.index(i) == 1 or columns.index(i) == 0:
tree.column(i, anchor=CENTER, width=120)
for row in self.data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
y_scrollbar = ttk.Scrollbar(self, orient='vertical', command=tree.yview)
x_scrollbar = ttk.Scrollbar(frame, orient="horizontal", command=tree.xview)
tree.configure(yscrollcommand=y_scrollbar.set)
tree.config(height=6)
tree.grid(row=0, column=0, columnspan=2, sticky=NSEW, pady=5)
y_scrollbar.grid(row=1, column=3, sticky='ns')
x_scrollbar.grid(row=2, column=0, columnspan=2, sticky='ew')
frame.grid_propagate(False)
def load(self):
# 加载数据
self.data_frame = pd.read_sql(f"select * from {self.table_name}", self.conn)
self.create_tree_widget()
class FormElement(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.default_query_sql = "select * from student"
self.create_form()
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn))
def create_form(self):
self.sid_var = IntVar()
self.sname_var = IntVar()
self.sclass_var = IntVar()
self.ssex_var = IntVar()
self.sage_var = IntVar()
self.score_var = IntVar()
self.courseId_var = IntVar()
self.cname_var = IntVar()
self.credit_var = IntVar()
self.chours_var = IntVar()
Label(self, text="学生/student", font=("Lucida Grande", 20), style="inverse").grid(row=0, column=0, sticky=W)
Label(self, text="学号", font=self.font_style).grid(row=1, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sid_var).grid(row=1, column=1, sticky=W)
self.sid = Entry(self, width=20, font=self.font_style)
self.sid.grid(row=1, column=2, sticky=W)
Label(self, text="姓名", font=self.font_style).grid(row=1, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sname_var).grid(row=1, column=4, sticky=W)
self.sname = Entry(self, width=20, font=self.font_style)
self.sname.grid(row=1, column=5, sticky=W)
Label(self, text="班级", font=self.font_style).grid(row=2, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sclass_var).grid(row=2, column=1, sticky=W)
self.sclass = Entry(self, width=20, font=self.font_style)
self.sclass.grid(row=2, column=2, sticky=W)
Label(self, text="性别", font=self.font_style).grid(row=2, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.ssex_var).grid(row=2, column=4, sticky=W)
self.ssex = Entry(self, width=20, font=self.font_style)
self.ssex.grid(row=2, column=5, sticky=W, pady=10)
Label(self, text="年龄自", font=self.font_style).grid(row=3, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sage_var).grid(row=3, column=1, sticky=W)
self.start_age = Entry(self, width=20, font=self.font_style)
self.start_age.grid(row=3, column=2, sticky=W)
Label(self, text="", font=self.font_style).grid(row=3, column=3, sticky=E)
Label(self, text="", font=self.font_style).grid(row=3, column=4, sticky=W)
self.end_age = Entry(self, width=20, font=self.font_style)
self.end_age.grid(row=3, column=5, sticky=W, pady=10)
Label(self, text="课程/course", font=("Lucida Grande", 20), style="inverse").grid(row=4, column=0, sticky=W)
Label(self, text="课号", font=self.font_style).grid(row=5, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.courseId_var).grid(row=5, column=1, sticky=W)
self.course_id = Entry(self, width=20, font=self.font_style)
self.course_id.grid(row=5, column=2, sticky=W)
Label(self, text="课名", font=self.font_style).grid(row=5, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.cname_var).grid(row=5, column=4, sticky=W)
self.course_name = Entry(self, width=20, font=self.font_style)
self.course_name.grid(row=5, column=5, sticky=W, pady=10)
Label(self, text="选课/sc", font=("Lucida Grande", 20), style="inverse").grid(row=6, column=0, sticky=W)
Label(self, text="成绩大于", font=self.font_style).grid(row=7, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.score_var).grid(row=7, column=1, sticky=W)
self.sc_start = Entry(self, width=20, font=self.font_style)
self.sc_start.grid(row=7, column=2, sticky=W)
Label(self, text="小于", font=self.font_style).grid(row=7, column=3, sticky=E)
Label(self, text="", font=self.font_style).grid(row=7, column=4, sticky=W)
self.sc_end = Entry(self, width=20, font=self.font_style)
self.sc_end.grid(row=7, column=5, sticky=W, pady=10)
Button(self, text="\n\n构造SQL\n\n", command=self.make_sql, width=8,
).grid(column=8, row=0, rowspan=8)
self.sql_text = Text(self, height=3, font=self.font_style, width=75)
self.sql_text.grid(row=8, column=0, rowspan=2, columnspan=7, sticky=W)
Button(self, text="\n执行SQL\n", command=self.execute_sql, width=8,
).grid(column=8, row=8, rowspan=2, padx=10)
self.sql_text.insert(1.0, self.default_query_sql)
def execute_sql(self):
sql = get_text_content(self.sql_text).lower().strip()
if sql.startswith("select"):
data_frame = pd.read_sql(sql, con=self.conn)
self.create_treeview(data_frame)
ToastNotification(message="语句执行成功",
title="提示",
duration=1500,
position=(int(self.winfo_screenwidth() / 2) - 150, 80, "ne"),
bootstyle="success",
icon="").show_toast()
def create_treeview(self, data_frame):
frame = Frame(self, height=400)
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = data_frame.keys().tolist()
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50,
selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, minwidth=100, width=100)
for row in data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview)
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False)
def make_sql(self):
sql = "select * from student where 1=1"
if self.course_id and self.course_name and self.sc_start and self.sc_end != "":
sql = "select * from student s join sc on sc.sid=s.sid join course c on c.cid=sc.cid"
if self.sid.get() != "":
sql += f" and (s.sid like '{self.sid.get()}')"
if self.sname.get() != "":
sql += f" and (s.sname like '{self.sname.get()}')"
if self.sclass.get() != "":
sql += f" and (s.sclass like '{self.sclass.get()}')"
if self.ssex.get() != "":
sql += f" and (s.ssex like '{self.ssex.get()}')"
if self.start_age.get() != "":
sql += f" and (s.sage > '{self.start_age.get()}')"
if self.end_age.get() != "":
sql += f" and (s.sage < '{self.end_age.get()}')"
if self.course_id.get() != "":
sql += f" and (c.cid like '{self.course_id.get()}')"
if self.course_name.get() != "":
sql += f" and (c.cname like '{self.course_name.get()}')"
if self.sc_start.get() != "":
sql += f" and (sc.score > {self.sc_start.get()})"
if self.sc_end.get() != "":
sql += f" and (sc.score < {self.sc_end.get()})"
else:
if self.sid.get() != "":
sql += f" and (sid like '{self.sid.get()}')"
if self.sname.get() != "":
sql += f" and (sname like '{self.sname.get()}')"
if self.sclass.get() != "":
sql += f" and (sclass like '{self.sclass.get()}')"
if self.start_age.get() != "":
sql += f" and (sage > '{self.start_age.get()}')"
if self.end_age.get() != "":
sql += f" and (sage < '{self.end_age.get()}')"
if sql == "select * from student where 1=1":
sql = "select * from student"
if (self.sid_var and self.ssex_var and self.sage_var and self.sclass_var and self.sname_var and self.score_var and self.cname_var and self.credit_var and self.chours_var == 0):
pass
else:
data = []
data.append("s.sid")if self.sid_var.get() == 1 else ""
data.append("s.sname")if self.sname_var.get() == 1 else ""
data.append("s.ssex")if self.ssex_var.get() == 1 else ""
data.append("s.sage")if self.sage_var.get() == 1 else ""
data.append("s.sclass")if self.sclass_var.get() == 1 else ""
data.append("sc.score")if self.score_var.get() == 1 else ""
data.append("c.cid")if self.courseId_var.get() == 1 else ""
data.append("c.cname")if self.cname_var.get() == 1 else ""
data.append("c.credit")if self.credit_var.get() == 1 else ""
data.append("c.chours")if self.chours_var.get() == 1 else ""
sql = sql.replace("select *", f"select {', '.join(data)} ")
sql = sql.replace("1=1 and", "")
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, sql)
class StuSys_X4(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
def create_left_plate(self):
self.left_frame = Frame(self.master, height=self.attr["height"])
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "sc")
load_element2.pack(side=TOP, pady=10)
def create_right_plate(self):
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
form_element = FormElement(self.right_frame)
form_element.pack(side=TOP, pady=10, anchor=NE)
if __name__ == '__main__':
"""
minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
cyborg, vapor, simplex, cerculean,
"""
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
"width": screenwidth * 0.83,
"height": screenheight * 0.85,
}
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
app = StuSys_X4(root, root_attr)
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

@ -0,0 +1,315 @@
from tkinter import Frame, messagebox
import tkinter.font as tkFont
from pandas import DataFrame
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from ttkbootstrap.toast import ToastNotification
from BaseWindow import BaseWindow
import warnings
warnings.simplefilter(action='ignore', category=UserWarning)
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
class LoadElement(Frame):
def __init__(self, master, table_name):
super().__init__(master)
self.master = master
self.table_name = table_name
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.data_frame = pd.read_sql(f"select * from {self.table_name} limit 0", self.conn)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.create_widget()
self.select_value(None)
self.create_tree_widget()
def select_value(self, event):
self.table_name = self.select_stringVar.get()
def get_table(self) -> DataFrame:
TableList = pd.read_sql("show tables", self.conn)
return TableList
def create_widget(self):
data_frame = self.get_table()
tables = [i[0] for i in data_frame.values.tolist()]
style = ttk.Style()
# 设置字体和字体大小
style.configure('TCombobox', font=('Arial', 100))
self.select_stringVar = StringVar()
self.select_stringVar.set(self.table_name)
self.combo = ttk.Combobox(self, width=10, height=1, textvariable=self.select_stringVar, font=self.font_style, style="TCombobox")
self.combo["values"] = tables
self.combo.bind('<<ComboboxSelected>>', self.select_value)
self.combo.grid(column=0, row=0)
Button(self, text="装载", width=10, command=self.load).grid(column=1, row=0, padx=5)
def create_tree_widget(self):
frame = Frame(self, width=50, height=220)
frame.grid(row=1, column=0, columnspan=2, sticky=NSEW, pady=5)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = self.data_frame.keys().tolist()
style = ttk.Style()
style.configure("Custom.Treeview.Heading", font=("宋体", 15))
style.configure("Custom.Treeview", rowheight=30, font=("宋体", 15))
tree = ttk.Treeview(frame, columns=columns, show="headings", style="Custom.Treeview", selectmode=BROWSE)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, width=80)
if columns.index(i) == 1 or columns.index(i) == 0:
tree.column(i, anchor=CENTER, width=120)
for row in self.data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
y_scrollbar = ttk.Scrollbar(self, orient='vertical', command=tree.yview)
x_scrollbar = ttk.Scrollbar(frame, orient="horizontal", command=tree.xview)
tree.configure(yscrollcommand=y_scrollbar.set)
tree.config(height=6)
tree.grid(row=0, column=0, columnspan=2, sticky=NSEW, pady=5)
y_scrollbar.grid(row=1, column=3, sticky='ns')
x_scrollbar.grid(row=2, column=0, columnspan=2, sticky='ew')
frame.grid_propagate(False)
def load(self):
# 加载数据
self.data_frame = pd.read_sql(f"select * from {self.table_name}", self.conn)
self.create_tree_widget()
class FormElement(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.default_query_sql = "select * from student"
self.create_form()
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn))
def create_form(self):
self.sid_var = IntVar()
self.sname_var = IntVar()
self.sclass_var = IntVar()
self.ssex_var = IntVar()
self.sage_var = IntVar()
self.score_var = IntVar()
self.courseId_var = IntVar()
self.cname_var = IntVar()
self.credit_var = IntVar()
self.chours_var = IntVar()
Label(self, text="学生/student", font=("Lucida Grande", 20), style="inverse").grid(row=0, column=0, sticky=W)
Label(self, text="学号", font=self.font_style).grid(row=1, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sid_var).grid(row=1, column=1, sticky=W)
self.sid = Entry(self, width=20, font=self.font_style)
self.sid.grid(row=1, column=2, sticky=W)
Label(self, text="姓名", font=self.font_style).grid(row=1, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sname_var).grid(row=1, column=4, sticky=W)
self.sname = Entry(self, width=20, font=self.font_style)
self.sname.grid(row=1, column=5, sticky=W)
Label(self, text="班级", font=self.font_style).grid(row=2, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sclass_var).grid(row=2, column=1, sticky=W)
self.sclass = Entry(self, width=20, font=self.font_style)
self.sclass.grid(row=2, column=2, sticky=W)
Label(self, text="性别", font=self.font_style).grid(row=2, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.ssex_var).grid(row=2, column=4, sticky=W)
self.ssex = Entry(self, width=20, font=self.font_style)
self.ssex.grid(row=2, column=5, sticky=W, pady=10)
Label(self, text="年龄自", font=self.font_style).grid(row=3, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.sage_var).grid(row=3, column=1, sticky=W)
self.start_age = Entry(self, width=20, font=self.font_style)
self.start_age.grid(row=3, column=2, sticky=W)
Label(self, text="", font=self.font_style).grid(row=3, column=3, sticky=E)
Label(self, text="", font=self.font_style).grid(row=3, column=4, sticky=W)
self.end_age = Entry(self, width=20, font=self.font_style)
self.end_age.grid(row=3, column=5, sticky=W, pady=10)
Label(self, text="课程/course", font=("Lucida Grande", 20), style="inverse").grid(row=4, column=0, sticky=W)
Label(self, text="课号", font=self.font_style).grid(row=5, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.courseId_var).grid(row=5, column=1, sticky=W)
self.course_id = Entry(self, width=20, font=self.font_style)
self.course_id.grid(row=5, column=2, sticky=W)
Label(self, text="课名", font=self.font_style).grid(row=5, column=3, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.cname_var).grid(row=5, column=4, sticky=W)
self.course_name = Entry(self, width=20, font=self.font_style)
self.course_name.grid(row=5, column=5, sticky=W, pady=10)
Label(self, text="选课/sc", font=("Lucida Grande", 20), style="inverse").grid(row=6, column=0, sticky=W)
Label(self, text="成绩大于", font=self.font_style).grid(row=7, column=0, sticky=E)
Checkbutton(self, onvalue=1, offvalue=0, variable=self.score_var).grid(row=7, column=1, sticky=W)
self.sc_start = Entry(self, width=20, font=self.font_style)
self.sc_start.grid(row=7, column=2, sticky=W)
Label(self, text="小于", font=self.font_style).grid(row=7, column=3, sticky=E)
Label(self, text="", font=self.font_style).grid(row=7, column=4, sticky=W)
self.sc_end = Entry(self, width=20, font=self.font_style)
self.sc_end.grid(row=7, column=5, sticky=W, pady=10)
Button(self, text="\n\n构造SQL\n\n", command=self.make_sql, width=8,
).grid(column=8, row=0, rowspan=8)
self.sql_text = Text(self, height=3, font=self.font_style, width=75)
self.sql_text.grid(row=8, column=0, rowspan=2, columnspan=7, sticky=W)
Button(self, text="\n执行SQL\n", command=self.execute_sql, width=8,
).grid(column=8, row=8, rowspan=2, padx=10)
self.sql_text.insert(1.0, self.default_query_sql)
def execute_sql(self):
cursor = self.conn.cursor()
try:
sql = get_text_content(self.sql_text).lower().strip()
cursor.execute(sql)
if sql.startswith("select"):
data_frame = pd.read_sql(sql, con=self.conn)
self.create_treeview(data_frame)
ToastNotification(message="语句执行成功",
title="提示",
duration=1500,
position=(int(self.winfo_screenwidth() / 2) - 150, 80, "ne"),
bootstyle="success",
icon="").show_toast()
except pymysql.Error as e:
messagebox.showerror(str(e.args[0]), str(e.args[1]))
finally:
cursor.close()
def create_treeview(self, data_frame):
frame = Frame(self, height=400)
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = data_frame.keys().tolist()
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50,
selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, minwidth=100, width=100)
for row in data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview)
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False)
def make_sql(self):
sql = "select * from student where 1=1"
if self.course_id and self.course_name and self.sc_start and self.sc_end != "":
sql = "select * from student s join sc on sc.sid=s.sid join course c on c.cid=sc.cid"
if self.sid.get() != "":
sql += f" and (s.sid like '{self.sid.get()}')"
if self.sname.get() != "":
sql += f" and (s.sname like '{self.sname.get()}')"
if self.sclass.get() != "":
sql += f" and (s.sclass like '{self.sclass.get()}')"
if self.ssex.get() != "":
sql += f" and (s.ssex like '{self.ssex.get()}')"
if self.start_age.get() != "":
sql += f" and (s.sage > '{self.start_age.get()}')"
if self.end_age.get() != "":
sql += f" and (s.sage < '{self.end_age.get()}')"
if self.course_id.get() != "":
sql += f" and (c.cid like '{self.course_id.get()}')"
if self.course_name.get() != "":
sql += f" and (c.cname like '{self.course_name.get()}')"
if self.sc_start.get() != "":
sql += f" and (sc.score > {self.sc_start.get()})"
if self.sc_end.get() != "":
sql += f" and (sc.score < {self.sc_end.get()})"
else:
if self.sid.get() != "":
sql += f" and (sid like '{self.sid.get()}')"
if self.sname.get() != "":
sql += f" and (sname like '{self.sname.get()}')"
if self.sclass.get() != "":
sql += f" and (sclass like '{self.sclass.get()}')"
if self.start_age.get() != "":
sql += f" and (sage > '{self.start_age.get()}')"
if self.end_age.get() != "":
sql += f" and (sage < '{self.end_age.get()}')"
if sql == "select * from student where 1=1":
sql = "select * from student"
if (self.sid_var and self.ssex_var and self.sage_var and self.sclass_var and self.sname_var and self.score_var and self.cname_var and self.credit_var and self.chours_var == 0):
pass
else:
data = []
data.append("s.sid")if self.sid_var.get() == 1 else ""
data.append("s.sname")if self.sname_var.get() == 1 else ""
data.append("s.ssex")if self.ssex_var.get() == 1 else ""
data.append("s.sage")if self.sage_var.get() == 1 else ""
data.append("s.sclass")if self.sclass_var.get() == 1 else ""
data.append("sc.score")if self.score_var.get() == 1 else ""
data.append("c.cid")if self.courseId_var.get() == 1 else ""
data.append("c.cname")if self.cname_var.get() == 1 else ""
data.append("c.credit")if self.credit_var.get() == 1 else ""
data.append("c.chours")if self.chours_var.get() == 1 else ""
sql = sql.replace("select *", f"select {', '.join(data)} ")
sql = sql.replace("1=1 and", "")
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, sql)
class StuSys_X4(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
def create_left_plate(self):
self.left_frame = Frame(self.master, height=self.attr["height"])
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "sc")
load_element2.pack(side=TOP, pady=10)
def create_right_plate(self):
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
form_element = FormElement(self.right_frame)
form_element.pack(side=TOP, pady=10, anchor=NE)
if __name__ == '__main__':
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
"width": screenwidth * 0.83,
"height": screenheight * 0.85,
}
# 配置界面大小
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False) # 禁止用户调整界面大小
app = StuSys_X4(root, root_attr)
app.create_left_plate()
app.create_right_plate()
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

@ -0,0 +1,309 @@
import uuid
from tkinter import messagebox
import tkinter.font as tkFont
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from BaseWindow import BaseWindow
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
class LoadElement(Frame):
def __init__(self, master, table_name):
super().__init__(master)
self.master = master
self.table_name = table_name
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.data_frame = pd.read_sql(f"select * from {self.table_name} limit 0", self.conn)
#左侧三框框数据
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.create_widget()
self.select_value(None)
self.create_tree_widget()
def select_value(self, event):
self.table_name = self.select_stringVar.get()
def create_widget(self):
data_frame = pd.read_sql("show tables", self.conn)
tables = [i[0] for i in data_frame.values.tolist()]
style = ttk.Style()
# 设置字体和字体大小
style.configure('TCombobox', font=('Arial', 100))
self.select_stringVar = StringVar()
self.select_stringVar.set(self.table_name)
combo = ttk.Combobox(self, width=10, height=1, textvariable=self.select_stringVar, font=self.font_style,
style="TCombobox")
combo["values"] = tables
combo.bind('<<ComboboxSelected>>', self.select_value)
combo.grid(column=0, row=0)
Button(self, text="装载", width=9, command=self.load).grid(column=1, row=0, padx=5)
def create_tree_widget(self):
# 创建画布,用于展示装载后的数据
frame = Frame(self, width=50, height=250)
frame.grid(row=1, column=0, columnspan=2, sticky=NSEW, pady=5)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = self.data_frame.keys().tolist()
style = ttk.Style()
style.configure("Custom.Treeview.Heading", font=("宋体", 15))
style.configure("Custom.Treeview", rowheight=30, font=("宋体", 15))
tree = ttk.Treeview(frame, columns=columns, show="headings", style="Custom.Treeview", selectmode=BROWSE)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, width=80)
if columns.index(i) == 1 or columns.index(i) == 0:
tree.column(i, anchor=CENTER, width=120)
for row in self.data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
y_scrollbar = ttk.Scrollbar(self, orient='vertical', command=tree.yview)
x_scrollbar = ttk.Scrollbar(frame, orient="horizontal", command=tree.xview)
tree.configure(yscrollcommand=y_scrollbar.set)
tree.config(height=6)
tree.grid(row=0, column=0, columnspan=2, sticky=NSEW, pady=5)
y_scrollbar.grid(row=1, column=3, sticky='ns')
x_scrollbar.grid(row=2, column=0, columnspan=2, sticky='ew')
frame.grid_propagate(False)
def load(self):
# 加载数据
self.data_frame = pd.read_sql(f"select * from {self.table_name}", self.conn)
self.create_tree_widget()
class FormElement(Frame):
def __init__(self, master, node):
super().__init__(master)
self.node = node
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.table_names = []
self.form_content = {}
self.get_table_names()
self.table_name = self.table_names[0]
self.default_query_sql = f"SELECT * FROM {self.table_name}"
self.create_form()
self.select_table(None)
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn))
def get_table_names(self):
"""
获取该数据库下所有的表
:return:
"""
data_frame = pd.read_sql("show tables", self.conn)
self.table_names = [i[0] for i in data_frame.values.tolist()]
def select_table(self, event):
"""
当下拉框选择表之后触发该函数并将tableName改为选择的tableName
:param event:
:return:
"""
for value in self.form_content.values():
value[0].grid_forget()
value[2].grid_forget()
value[3].grid_forget()
self.form_content.clear()
self.table_name = self.select_table_name.get()
self.create_form()
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, f"SELECT * FROM {self.table_name}")
def get_field_names(self):
"""
获取所有数据表的所有字段
:return: 返回表内的所有字段
"""
data_frame = pd.read_sql(f"desc {self.table_name}", self.conn)
"""
field_names = []
for field in data_frame["Field"]:
field_names.append(f"{self.table_name}.{field}")
return field_names
"""
return data_frame["Field"].values.tolist()
def create_form(self):
"""
创建表单区域根据数据表自动生成表单
:return:
"""
self.select_table_name = StringVar()
self.select_table_name.set(self.table_name)
combo = ttk.Combobox(self, width=8, height=1, textvariable=self.select_table_name, font=self.font_style,
style="TCombobox")
combo["values"] = self.table_names
combo.bind('<<ComboboxSelected>>', self.select_table)
combo.grid(column=0, row=0, sticky=W)
fields = self.get_field_names()
num_fields = len(fields)
num_rows = (num_fields + 1) // 2
for i in range(num_rows):
for j in range(2):
field_idx = i * 2 + j
if field_idx >= num_fields:
break
field_name = fields[field_idx]
label = Label(self, text=field_name, font=self.font_style)
label.grid(row=i + 1, column=j * 2, padx=5, pady=5, sticky=W)
checkbutton_var = IntVar()
checkbutton = Checkbutton(self, text='', variable=checkbutton_var)
checkbutton.grid(row=i + 1, column=j * 2, padx=5, pady=5, sticky=E)
entry = Entry(self, font=self.font_style)
entry.grid(row=i + 1, column=j * 2 + 1, padx=5, pady=5, sticky=W)
self.form_content[field_name] = (entry, checkbutton_var, label, checkbutton)
style = Style()
style.configure("custom.TButton", padding=(10, 40, 10, 40))
Button(self, text="构造SQL", command=self.make_sql, width=8, style="custom.TButton"
).grid(column=8, row=0, rowspan=8)
self.sql_text = Text(self, height=3, font=self.font_style, width=62)
self.sql_text.grid(row=8, column=0, rowspan=2, columnspan=7, sticky=W)
Button(self, text="\n执行SQL\n", command=self.execute_sql, width=8,
).grid(column=8, row=8, rowspan=2, padx=10)
self.sql_text.insert(1.0, self.default_query_sql)
def execute_sql(self):
cursor = self.conn.cursor()
sql = get_text_content(self.sql_text).lower().strip()
try:
cursor.execute(sql)
if sql.startswith("select"):
data_frame = pd.read_sql(sql, con=self.conn)
self.create_treeview(data_frame)
self.node.message.insert(0, f"{sql}执行成功!共查询到{len(data_frame)}条数据-{uuid.uuid4()}-true")
return
self.node.message.insert(0, f"{sql}执行成功!-{uuid.uuid4()}-true")
except pymysql.Error as e:
messagebox.showerror(str(e.args[0]), str(e.args[1]))
self.node.message.insert(0, f"{sql}执行失败!{e}-{uuid.uuid4()}-false")
finally:
cursor.close()
self.node.update_message()
def create_treeview(self, data_frame):
frame = Frame(self, height=580)
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW, pady=10)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
unique_columns = data_frame.columns[~data_frame.columns.duplicated()]
columns = unique_columns.tolist()
# 获取查询的列名,将其转换为列表
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50, selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, minwidth=100, width=100)
for row in data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview)
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False)
def make_sql(self):
sql = f"SELECT * FROM {self.table_name}"
conditions = []
select_fields = []
for field, (entry, checkbox_var, i, j) in self.form_content.items():
if entry.get():
conditions.append("{} like '{}'".format(field, entry.get()))
if checkbox_var.get() == 1:
select_fields.append("{}".format(field))
if conditions:
sql = "SELECT * FROM {} WHERE {}".format(self.table_name, " AND ".join(conditions))
if select_fields:
sql = sql.replace("*", ",".join(select_fields))
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, sql)
class StuSys_X4(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
self.message = []
def create_left_plate(self):
self.left_frame = Frame(self.master, height=self.attr["height"])
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=RIGHT, anchor=NW, pady=10, padx=10)
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "sc")
load_element2.pack(side=TOP, pady=10)
message_frame = Frame(self.right_frame, width=50, height=180)
message_frame.pack(side=TOP, pady=10, fill=BOTH)
self.canvas = Canvas(message_frame, width=280, height=1000, bg="#f0f5fa")
self.canvas.configure(background="#f0f5fa")
y_scrollbar = Scrollbar(message_frame, orient="vertical", command=self.canvas.yview)
x_scrollbar = Scrollbar(message_frame, orient="horizontal", command=self.canvas.xview)
y_scrollbar.pack(side=RIGHT, fill=BOTH)
x_scrollbar.pack(side=BOTTOM, fill=BOTH)
self.canvas.pack(side=TOP, fill=BOTH)
self.canvas.configure(yscrollcommand=y_scrollbar.set)
self.canvas.configure(xscrollcommand=x_scrollbar.set)
def update_message(self):
self.canvas.delete(ALL)
for message in self.message:
index = self.message.index(message)
self.canvas.create_text(0, 20 * index, anchor="nw",
text=message.split("-")[0], font=("", 15), fill="black" if message.split("-")[-1] == "true" else "red")
self.canvas.update()
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def create_right_plate(self):
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
form_element = FormElement(self.right_frame, self)
form_element.pack(side=TOP, pady=10, anchor=NE)
if __name__ == '__main__':
"""
minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
cyborg, vapor, simplex, cerculean,
"""
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
"width": screenwidth * 0.88,
"height": screenheight * 0.90,
}
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
app = StuSys_X4(root, root_attr)
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

@ -0,0 +1,335 @@
import uuid
import random
from tkinter import messagebox
import tkinter.font as tkFont
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from BaseWindow import BaseWindow
import warnings
warnings.simplefilter(action='ignore', category=UserWarning)
# 添加第三个任务
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
class LoadElement(Frame):
def __init__(self, master, table_name):
super().__init__(master)
self.master = master
self.table_name = table_name
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.data_frame = pd.read_sql(f"select * from {self.table_name} limit 0", self.conn)
#左侧三框框数据
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.create_widget()
self.select_value(None)
self.create_tree_widget()
def select_value(self, event):
self.table_name = self.select_stringVar.get()
def create_widget(self):
data_frame = pd.read_sql("show tables", self.conn)
tables = [i[0] for i in data_frame.values.tolist()]
style = ttk.Style()
# 设置字体和字体大小
style.configure('TCombobox', font=('Arial', 100))
self.select_stringVar = StringVar()
self.select_stringVar.set(self.table_name)
combo = ttk.Combobox(self, width=10, height=1, textvariable=self.select_stringVar, font=self.font_style,
style="TCombobox")
combo["values"] = tables
combo.bind('<<ComboboxSelected>>', self.select_value)
combo.grid(column=0, row=0)
Button(self, text="装载", width=9, command=self.load).grid(column=1, row=0, padx=5)
def create_tree_widget(self):
# 创建画布,用于展示装载后的数据
frame = Frame(self, width=50, height=250)
frame.grid(row=1, column=0, columnspan=2, sticky=NSEW, pady=5)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = self.data_frame.keys().tolist()
style = ttk.Style()
style.configure("Custom.Treeview.Heading", font=("宋体", 15))
style.configure("Custom.Treeview", rowheight=30, font=("宋体", 15))
tree = ttk.Treeview(frame, columns=columns, show="headings", style="Custom.Treeview", selectmode=BROWSE)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, width=80)
if columns.index(i) == 1 or columns.index(i) == 0:
tree.column(i, anchor=CENTER, width=120)
for row in self.data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
y_scrollbar = ttk.Scrollbar(self, orient='vertical', command=tree.yview)
x_scrollbar = ttk.Scrollbar(frame, orient="horizontal", command=tree.xview)
tree.configure(yscrollcommand=y_scrollbar.set)
tree.config(height=6)
tree.grid(row=0, column=0, columnspan=2, sticky=NSEW, pady=5)
y_scrollbar.grid(row=1, column=3, sticky='ns')
x_scrollbar.grid(row=2, column=0, columnspan=2, sticky='ew')
frame.grid_propagate(False)
def load(self):
# 加载数据
self.data_frame = pd.read_sql(f"select * from {self.table_name}", self.conn)
self.create_tree_widget()
class FormElement(Frame):
def __init__(self, master, node):
super().__init__(master)
self.node = node
self.data = []
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.table_names = []
self.form_content = {}
self.get_table_names()
self.table_name = self.table_names[0]
self.default_query_sql = f"SELECT * FROM {self.table_name}"
self.create_form()
self.select_table(None)
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn))
def get_table_names(self):
"""
获取该数据库下所有的表
:return:
"""
data_frame = pd.read_sql("show tables", self.conn)
self.table_names = [i[0] for i in data_frame.values.tolist()]
def select_table(self, event):
"""
当下拉框选择表之后触发该函数并将tableName改为选择的tableName
:param event:
:return:
"""
for value in self.form_content.values():
value[0].grid_forget()
value[2].grid_forget()
value[3].grid_forget()
self.form_content.clear()
self.table_name = self.select_table_name.get()
self.create_form()
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, f"SELECT * FROM {self.table_name}")
def get_field_names(self):
"""
获取所有数据表的所有字段
:return: 返回表内的所有字段
"""
data_frame = pd.read_sql(f"desc {self.table_name}", self.conn)
"""
field_names = []
for field in data_frame["Field"]:
field_names.append(f"{self.table_name}.{field}")
return field_names
"""
return data_frame["Field"].values.tolist()
def create_form(self):
"""
创建表单区域根据数据表自动生成表单
:return:
"""
self.select_table_name = StringVar()
self.select_table_name.set(self.table_name)
combo = ttk.Combobox(self, width=8, height=1, textvariable=self.select_table_name, font=self.font_style,
style="TCombobox")
combo["values"] = self.table_names
combo.bind('<<ComboboxSelected>>', self.select_table)
combo.grid(column=0, row=0, sticky=W)
fields = self.get_field_names()
num_fields = len(fields)
num_rows = (num_fields + 1) // 2
for i in range(num_rows):
for j in range(2):
field_idx = i * 2 + j
if field_idx >= num_fields:
break
field_name = fields[field_idx]
label = Label(self, text=field_name, font=self.font_style)
label.grid(row=i + 1, column=j * 2, padx=5, pady=5, sticky=W)
checkbutton_var = IntVar()
checkbutton = Checkbutton(self, text='', variable=checkbutton_var)
checkbutton.grid(row=i + 1, column=j * 2, padx=5, pady=5, sticky=E)
entry = Entry(self, font=self.font_style)
entry.grid(row=i + 1, column=j * 2 + 1, padx=5, pady=5, sticky=W)
self.form_content[field_name] = (entry, checkbutton_var, label, checkbutton)
style = Style()
style.configure("custom.TButton", padding=(10, 40, 10, 40))
Button(self, text="构造SQL", command=self.make_sql, width=8, style="custom.TButton"
).grid(column=8, row=0, rowspan=8)
self.sql_text = Text(self, height=3, font=self.font_style, width=62)
self.sql_text.grid(row=8, column=0, rowspan=2, columnspan=7, sticky=W)
Button(self, text="\n执行SQL\n", command=self.execute_sql, width=8,
).grid(column=8, row=8, rowspan=2, padx=10)
self.sql_text.insert(1.0, self.default_query_sql)
def execute_sql(self):
cursor = self.conn.cursor()
# 获取文本框中的sql语句
sql = get_text_content(self.sql_text).lower().strip()
try:
cursor.execute(sql)
# 如果是查询语句
if sql.startswith("select"):
data_frame = pd.read_sql(sql, con=self.conn)
self.create_treeview(data_frame)
self.node.message.insert(0, f"{sql}执行成功!共查询到{len(data_frame)}条数据-{uuid.uuid4()}-true") # uuid标识事件的唯一性
return
# 如果不是查询语句
self.node.message.insert(0, f"{sql}执行成功!-{uuid.uuid4()}-true")
except pymysql.Error as e:
messagebox.showerror(str(e.args[0]), str(e.args[1]))
self.node.message.insert(0, f"{sql}执行失败!{e}-{uuid.uuid4()}-false")
finally:
cursor.close()
self.node.update_message()
def create_treeview(self, data_frame):
frame = Frame(self, height=580)
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW, pady=10)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
unique_columns = data_frame.columns[~data_frame.columns.duplicated()]
columns = unique_columns.tolist()
# 获取查询的列名,将其转换为列表
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50, selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i)
for i in columns:
tree.column(i, anchor=CENTER, minwidth=100, width=100)
for row in data_frame.itertuples():
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview)
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False)
def make_sql(self):
sql = f"SELECT * FROM {self.table_name}"
conditions = []
select_fields = []
condition_statements = [
"{} LIKE '{}'",
"{} = '{}'",
"NOT ({} != '{}')",
"{} IN ('{}')"
]
for field, (entry, checkbox_var, i, j) in self.form_content.items():
if entry.get():
# conditions.append("{} like '{}'".format(field, entry.get()))
# conditions.append("{} = '{}'".format(field, entry.get()))
# conditions.append("NOT ({} != '{}')".format(field, entry.get()))
# conditions.append("{} IN ('{}')".format(field, entry.get()))
conditions.append(random.choice(condition_statements).format(field, entry.get()))
if checkbox_var.get() == 1:
select_fields.append("{}".format(field))
if conditions:
sql = "SELECT * FROM {} WHERE {}".format(self.table_name, " AND ".join(conditions))
print(sql)
if select_fields:
sql = sql.replace("*", ",".join(select_fields))
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, sql)
class StuSys_X4(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
self.message = []
def create_left_plate(self):
self.left_frame = Frame(self.master, height=self.attr["height"])
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=RIGHT, anchor=NW, pady=10, padx=10)
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element2 = LoadElement(self.left_frame, "sc")
load_element2.pack(side=TOP, pady=10)
message_frame = Frame(self.right_frame, width=50, height=180)
message_frame.pack(side=TOP, pady=10, fill=BOTH)
self.canvas = Canvas(message_frame, width=280, height=1000, bg="#f0f5fa")
self.canvas.configure(background="#f0f5fa")
y_scrollbar = Scrollbar(message_frame, orient="vertical", command=self.canvas.yview)
x_scrollbar = Scrollbar(message_frame, orient="horizontal", command=self.canvas.xview)
y_scrollbar.pack(side=RIGHT, fill=BOTH)
x_scrollbar.pack(side=BOTTOM, fill=BOTH)
self.canvas.pack(side=TOP, fill=BOTH)
self.canvas.configure(yscrollcommand=y_scrollbar.set)
self.canvas.configure(xscrollcommand=x_scrollbar.set)
def update_message(self):
self.canvas.delete(ALL)
for message in self.message:
index = self.message.index(message)
self.canvas.create_text(0, 20 * index, anchor="nw",
text=message.split("-")[0], font=("", 15), fill="black" if message.split("-")[-1] == "true" else "red")
self.canvas.update()
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def create_right_plate(self):
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
form_element = FormElement(self.right_frame, self)
form_element.pack(side=TOP, pady=10, anchor=NE)
if __name__ == '__main__':
"""
minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
cyborg, vapor, simplex, cerculean,
"""
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
"width": screenwidth * 0.88,
"height": screenheight * 0.90,
}
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
app = StuSys_X4(root, root_attr)
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

@ -0,0 +1,382 @@
import uuid
import random
from tkinter import messagebox
import tkinter.font as tkFont
from ttkbootstrap import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import pandas as pd
import pymysql
from ttkbootstrap.toast import ToastNotification
from BaseWindow import BaseWindow
import warnings
warnings.simplefilter(action='ignore', category=UserWarning)
def get_text_content(text):
return text.get("0.0", "end").replace("\n", " ")
class LoadElement(Frame):
def __init__(self, master, table_name):
super().__init__(master)
self.master = master
self.table_name = table_name # 默认装载的表名
self.data = []
# self.conn = pymysql.connect(user="root", password="123123", database="stu_sys", host="127.0.0.1", port=3306)
self.conn = pymysql.connect(user="root", password="Wyz010810", database="SCT", host="127.0.0.1", port=3306)
# self.data_frame = pd.read_sql(f"select * from {self.table_name} limit 0", self.conn)
self.data_frame = pd.DataFrame([]) # 创建一个空的 DataFrame。而不是执行获得并限制返回数量为0
# 定义字体和按钮的格式
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.create_widget()
self.select_value(None)
self.create_tree_widget()
# 获取下拉框中的table_name以供后续装载等使用
def select_value(self, event):
self.table_name = self.select_stringVar.get()
# 固定的版本
def create_widget_label(self):
# 不再需要查询数据库获取表名,也不需要创建下拉框
# data_frame = pd.read_sql("show tables", self.conn)
# tables = [i[0] for i in data_frame.values.tolist()]
style = ttk.Style()
# 设置 Label 的字体和字体大小
style.configure('TLabel', font=('Arial', 20)) # 根据需要调整字体大小
# 创建 Label 控件以显示表名
label = ttk.Label(self, text=self.table_name, font=self.font_style, style='TLabel')
label.grid(column=0, row=0)
# 创建装载按钮
Button(self, text="装载", width=9, command=self.load).grid(column=1, row=0, padx=5)
# 创建小控件,包括下拉按钮以及装载按钮
def create_widget(self):
data_frame = pd.read_sql("show tables", self.conn)
tables = [i[0] for i in data_frame.values.tolist()]
style = ttk.Style()
# 设置字体和字体大小
style.configure('TCombobox', font=('Arial', 100))
self.select_stringVar = StringVar()
self.select_stringVar.set(self.table_name)
combo = ttk.Combobox(self, width=10, height=1, textvariable=self.select_stringVar, font=self.font_style,
style="TCombobox")
combo["values"] = tables
combo.bind('<<ComboboxSelected>>', self.select_value)
combo.grid(column=0, row=0)
Button(self, text="装载", width=9, command=self.load).grid(column=1, row=0, padx=5)
# 创建一个带有滚动条并定义好样式的树形视图控件,用于显示查询结果
def create_tree_widget(self):
# 创建画布,用于展示装载后的数据
frame = Frame(self, width=50, height=250)
frame.grid(row=1, column=0, columnspan=2, sticky=NSEW, pady=5)
# 设置框架的列和行能够随窗口大小调整而伸缩。
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
columns = self.data_frame.keys().tolist()
style = ttk.Style()
style.configure("Custom.Treeview.Heading", font=("宋体", 15))
style.configure("Custom.Treeview", rowheight=30, font=("宋体", 15))
tree = ttk.Treeview(frame, columns=columns, show="headings", style="Custom.Treeview", selectmode=BROWSE)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i) # 为每个列设置标题
for i in columns:
tree.column(i, anchor=CENTER, width=80) # 为每个列设置对齐方式
if columns.index(i) == 1 or columns.index(i) == 0:
tree.column(i, anchor=CENTER, width=120)
for row in self.data_frame.itertuples(): # 将数据的每一行插入到树形视图中
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
y_scrollbar = ttk.Scrollbar(self, orient='vertical', command=tree.yview)
x_scrollbar = ttk.Scrollbar(frame, orient="horizontal", command=tree.xview)
tree.configure(yscrollcommand=y_scrollbar.set)
tree.config(height=6)
tree.grid(row=0, column=0, columnspan=2, sticky=NSEW, pady=5)
y_scrollbar.grid(row=1, column=3, sticky='ns')
x_scrollbar.grid(row=2, column=0, columnspan=2, sticky='ew')
frame.grid_propagate(False)
def load(self):
# 加载数据
self.data_frame = pd.read_sql(f"select * from {self.table_name}", self.conn)
self.create_tree_widget()
class FormElement(Frame):
def __init__(self, master, node):
super().__init__(master)
self.node = node
self.data = [] # 好像没用到
# self.conn = pymysql.connect(user="root", password="123123", database="stu_sys", host="127.0.0.1", port=3306)
self.conn = pymysql.connect(user="root", password="Wyz010810", database="sct", host="127.0.0.1", port=3306)
self.font_style = tkFont.Font(family="Lucida Grande", size=20)
self.button_font = tkFont.Font(family="Lucida Grande", size=10)
self.table_names = [] # 用于存储下拉表单的数据库表名
self.form_content = {}
self.get_table_names()
self.table_name = self.table_names[0]
self.default_query_sql = f"SELECT * FROM {self.table_name}"
self.create_form()
self.select_table(None)
self.create_treeview(pd.read_sql(self.default_query_sql, con=self.conn))
def select_table(self, event):
"""
当下拉框选择表之后触发该函数并将tableName改为选择的tableName
:param event:
:return:
"""
for value in self.form_content.values():
value[0].grid_forget()
value[2].grid_forget()
value[3].grid_forget()
self.form_content.clear()
self.table_name = self.select_table_name.get()
self.create_form()
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, f"SELECT * FROM {self.table_name}")
def get_table_names(self):
"""
获取该数据库下所有的表
:return:
"""
data_frame = pd.read_sql("show tables", self.conn)
self.table_names = [i[0] for i in data_frame.values.tolist()]
def get_field_names(self):
"""
获取所有数据表的所有字段
:return: 返回表内的所有字段
"""
data_frame = pd.read_sql(f"desc {self.table_name}", self.conn)
"""
field_names = []
for field in data_frame["Field"]:
field_names.append(f"{self.table_name}.{field}")
return field_names
"""
return data_frame["Field"].values.tolist()
def create_form(self):
"""
创建表单区域根据数据表自动生成表单
:return:
"""
self.select_table_name = StringVar() # 初始化一个StringVar对象用于存储当前选中的表名
self.select_table_name.set(self.table_name) # 设置默认表名
combo = ttk.Combobox(self, width=8, height=1, textvariable=self.select_table_name, font=self.font_style,
style="TCombobox") # 创建一个下拉选择框,允许用户选择一个数据表
combo["values"] = self.table_names # 设置下拉选项为所有表名
combo.bind('<<ComboboxSelected>>', self.select_table) # 绑定选择事件处理函数
combo.grid(column=0, row=0, sticky=W) # 放置组件
# 获取当前表的所有字段名
fields = self.get_field_names()
num_fields = len(fields)
num_rows = (num_fields + 1) // 2 # 计算需要的行数,以每行放置两个字段
# 根据字段生成表单元素
for i in range(num_rows):
for j in range(2): # 每行两列布局
field_idx = i * 2 + j
if field_idx >= num_fields:
break # 如果字段索引超出范围,则退出循环
field_name = fields[field_idx] # 获取字段名称
# 为每个字段创建一个标签
label = Label(self, text=field_name, font=self.font_style)
label.grid(row=i + 1, column=j * 2, padx=20, pady=5, sticky=W)
# 创建一个复选框,可能用于指示选择状态
checkbutton_var = IntVar()
checkbutton = Checkbutton(self, text='', variable=checkbutton_var)
checkbutton.grid(row=i + 1, column=j * 2, padx=0, pady=5, sticky=E)
# 创建一个文本输入框,用于输入或显示字段值
entry = Entry(self, font=self.font_style, width=12)
# entry = Entry(self, font=self.font_style)
entry.grid(row=i + 1, column=j * 2 + 1, padx=5, pady=5, sticky=W)
# 存储表单组件引用,以便后续使用
self.form_content[field_name] = (entry, checkbutton_var, label, checkbutton)
# 配置并创建一个"构造SQL"按钮
style = Style()
style.configure("custom.TButton", padding=(10, 40, 10, 40))
Button(self, text="构造SQL", command=self.make_sql, width=8, style="custom.TButton"
).grid(column=8, row=0, rowspan=8)
# 创建一个文本框用于显示或编辑SQL命令
self.sql_text = Text(self, height=3, font=self.font_style, width=46)
self.sql_text.grid(row=8, column=0, rowspan=2, columnspan=7, sticky=W)
# 创建一个"执行SQL"按钮用于执行文本框中的SQL命令
Button(self, text="\n执行SQL\n", command=self.execute_sql, width=8,
).grid(column=8, row=8, rowspan=2, padx=10)
# 插入默认的查询SQL
self.sql_text.insert(1.0, self.default_query_sql)
def execute_sql(self):
cursor = self.conn.cursor()
sql = get_text_content(self.sql_text).lower().strip() # 获取文本框中的sql语句
try:
cursor.execute(sql)
# 如果是查询语句
if sql.startswith("select"):
data_frame = pd.read_sql(sql, con=self.conn)
self.create_treeview(data_frame)
self.node.message.insert(0, f"{sql}执行成功!共查询到{len(data_frame)}条数据-{uuid.uuid4()}-true") # uuid标识事件的唯一性
return
# 如果不是查询语句
self.node.message.insert(0, f"{sql}执行成功!-{uuid.uuid4()}-true")
except pymysql.Error as e:
# 如果执行过程中遇到pymysql相关错误则弹出错误信息框
messagebox.showerror(str(e.args[0]), str(e.args[1]))
self.node.message.insert(0, f"{sql}执行失败!{e}-{uuid.uuid4()}-false")
finally:
cursor.close()
self.node.update_message()
# 创建一个带有滚动条并定义好样式的树形视图控件,用于显示查询结果
def create_treeview(self, data_frame):
frame = Frame(self, height=580)
frame.grid(row=10, column=0, columnspan=10, rowspan=5, sticky=NSEW, pady=10)
# 设置框架的列和行能够随窗口大小调整而伸缩。
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
unique_columns = data_frame.columns[~data_frame.columns.duplicated()]
columns = unique_columns.tolist()
# 获取查询的列名,将其转换为列表
tree = ttk.Treeview(frame, columns=columns, show="headings", style="mystyle.Treeview", height=50,
selectmode=BROWSE)
style = ttk.Style()
style.configure("Treeview.Heading", font=self.font_style)
style.configure("Treeview", rowheight=30, font=self.font_style, borderwidth=1)
# 根据dataFrame结构生成表
for i in columns:
tree.heading(column=i, text=i) # 为每个列设置标题
for i in columns:
tree.column(i, anchor=CENTER, minwidth=100, width=100) # 为每个列设置对齐方式
for row in data_frame.itertuples(): # 将数据的每一行插入到树形视图中
tree.insert(parent="", index=END, values=[row[i] for i in range(1, len(row))])
tree.grid(row=0, column=0, sticky=NSEW, pady=10)
y_scrollbar = ttk.Scrollbar(frame, orient='vertical', command=tree.yview)
tree.configure(yscrollcommand=y_scrollbar.set)
y_scrollbar.grid(row=0, column=1, sticky='ns')
frame.grid_propagate(False)
def make_sql(self):
sql = f"SELECT * FROM {self.table_name}"
conditions = []
select_fields = []
condition_statements = [
"{} LIKE '{}'",
"{} = '{}'",
"NOT ({} != '{}')",
"{} IN ('{}')"
]
for field, (entry, checkbox_var, i, j) in self.form_content.items():
if entry.get():
# conditions.append("{} like '{}'".format(field, entry.get()))
# conditions.append("{} = '{}'".format(field, entry.get()))
# conditions.append("NOT ({} != '{}')".format(field, entry.get()))
# conditions.append("{} IN ('{}')".format(field, entry.get()))
conditions.append(random.choice(condition_statements).format(field, entry.get()))
if checkbox_var.get() == 1:
select_fields.append("{}".format(field))
if conditions:
sql = "SELECT * FROM {} WHERE {}".format(self.table_name, " AND ".join(conditions))
print(sql)
if select_fields:
sql = sql.replace("*", ",".join(select_fields))
self.sql_text.delete(0.0, END)
self.sql_text.insert(1.0, sql)
# 该类用于创建一个界面窗口
class StuSys_X4(BaseWindow):
def __init__(self, master, attr):
super().__init__(master, attr)
self.create_left_plate()
self.create_right_plate()
self.message = []
# 这里创建了左边的三个小的查询的表
def create_left_plate(self):
# 创建左侧框架并打包定位
self.left_frame = Frame(self.master, height=self.attr["height"])
self.left_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
load_element1 = LoadElement(self.left_frame, "student")
load_element1.pack(side=TOP, pady=10)
# ...course与sc的装载表的创建方式类似
load_element2 = LoadElement(self.left_frame, "course")
load_element2.pack(side=TOP, pady=10)
load_element3 = LoadElement(self.left_frame, "sc")
load_element3.pack(side=TOP, pady=10)
# 以下是消息框部分的内容
# 创建右侧框架并打包定位
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=RIGHT, anchor=NW, pady=10, padx=10)
# 创建消息框架和画布,可能用于显示信息或更复杂的交互元素
message_frame = Frame(self.right_frame, width=50, height=180)
message_frame.pack(side=TOP, pady=10, fill=BOTH)
self.canvas = Canvas(message_frame, width=280, height=1000, bg="#f0f5fa")
self.canvas.configure(background="#f0f5fa")
# 配置滚动条
y_scrollbar = Scrollbar(message_frame, orient="vertical", command=self.canvas.yview)
x_scrollbar = Scrollbar(message_frame, orient="horizontal", command=self.canvas.xview)
y_scrollbar.pack(side=RIGHT, fill=BOTH)
x_scrollbar.pack(side=BOTTOM, fill=BOTH)
self.canvas.pack(side=TOP, fill=BOTH)
self.canvas.configure(yscrollcommand=y_scrollbar.set)
self.canvas.configure(xscrollcommand=x_scrollbar.set)
# 在查询后调用这个函数,更新查询记录部分
def update_message(self):
self.canvas.delete(ALL)
for message in self.message:
index = self.message.index(message)
self.canvas.create_text(0, 20 * index, anchor="nw",
text=message.split("-")[0], font=("", 15),
fill="black" if message.split("-")[-1] == "true" else "red")
self.canvas.update()
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def create_right_plate(self):
self.right_frame = Frame(self.master, height=self.attr["height"])
self.right_frame.pack(side=LEFT, anchor=NW, pady=10, padx=10)
form_element = FormElement(self.right_frame, self)
form_element.pack(side=TOP, pady=10, anchor=NE)
if __name__ == '__main__':
"""
minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly, superhero, solar
cyborg, vapor, simplex, cerculean,
"""
style = "morph"
root = Window(themename=style)
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
root_attr = {
"width": screenwidth * 0.88,
"height": screenheight * 0.90,
}
alignstr = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screenwidth - root_attr['width']) / 2,
(screenheight - root_attr['height']) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
app = StuSys_X4(root, root_attr)
ttk.Style().configure("TButton", font="-size 18")
root.mainloop()

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

@ -0,0 +1,63 @@
import pymysql
# 创建名为SCT的数据库
def create_database():
cursor = conn.cursor() # 创建游标
cursor.execute("DROP DATABASE IF EXISTS SCT")
# 创建数据库
cursor.execute("CREATE DATABASE SCT CHARACTER SET utf8 COLLATE utf8_general_ci")
cursor.close() # 关闭游标
# 创建数据库表
def create_table():
cursor = conn.cursor() # 创建游标
cursor.execute("USE SCT") # 指定数据库
# 创建student数据表
cursor.execute("""
CREATE TABLE IF NOT EXISTS student
(
sid CHAR(8) PRIMARY KEY,
sname CHAR(10),
ssex CHAR(2),
sage INTEGER,
sclass CHAR(6)
)
""")
# 创建Course数据表
cursor.execute("""
CREATE TABLE IF NOT EXISTS course
(
cid CHAR(4) PRIMARY KEY,
cname CHAR(30),
credit FLOAT(1),
chours INTEGER,
t CHAR(3)
)
""")
# 创建SC数据表
cursor.execute("""
CREATE TABLE IF NOT EXISTS sc
(
sid CHAR(8),
cid CHAR(4),
score FLOAT(1),
CONSTRAINT sc_course_cid_fk
FOREIGN KEY (cid) REFERENCES course (cid),
CONSTRAINT sc_student_sid_fk
FOREIGN KEY (sid) REFERENCES student (sid)
)
""")
cursor.close()
sql = """
INSERT INTO student VALUES ('20200001', '张三','',20,'01')
UPDATE student SET SClass = '02' WHERE S# = '20200001'
DELETE FROM student WHERE S# = '20200001'
SELECT * FROM student
"""
if __name__ == '__main__':
conn = pymysql.connect(user="root", password="123456", host="127.0.0.1", port=3306)
create_database()
create_table()
conn.close() # 关闭链接
Loading…
Cancel
Save