You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tree/FractalTree_copy.py

409 lines
22 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# encoding: utf-8
from tkinter import *
from tkinter import messagebox
from PIL import Image, ImageTk
import math
from time import sleep
from dbUtil import DbUtil
class Message(Canvas):
# todo: 日志消息类
def __init__(self, master, **kwargs):
super().__init__(master, **kwargs)
self.message = []
self.master = master
self.scrollbar = Scrollbar(master, orient="vertical", command=self.yview)
self.scrollbar.pack(side="right", fill=BOTH)
self.config(yscrollcommand=self.scrollbar.set)
def show_message(self, message, color="white"):
# todo: 添加日志消息
self.message.append({"message": message, "color": color})
num = 0
self.delete("message")
for function in self.message:
self.create_text(20, 25 * num + 10, anchor="nw", text=function["message"], font=("", 15), fill=function["color"], tags="message")
num += 1
self.update()
self.configure(scrollregion=self.bbox("all"))
self.scrollbar.set(1.0, 1.0)
self.yview_moveto(1.0)
class AddFractal(Toplevel):
def __init__(self, master, _type, fractal_id=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.transient(root)
self.master = master
self.type = _type
self.fractal_id = fractal_id
self.cv = Canvas(self, width=screen_width * 0.5, height=screen_height * 0.7)
self.cv.place(x=0, y=0, anchor=NW)
self.label_width, self.label_height = 140, 40
self.top_window_back_img = ImageTk.PhotoImage(
Image.open("./images/大背景@3x.jpg").resize((int(screen_width * 0.5), int(screen_height * 0.7))))
self.save_img = ImageTk.PhotoImage(Image.open("./images/保存@3x.png").resize((100, self.label_height)))
self.update_img = ImageTk.PhotoImage(Image.open("./images/修改@3x.png").resize((100, self.label_height)))
self.add_var_img = ImageTk.PhotoImage(Image.open("./images/添加变量@3x.png").resize((100, self.label_height)))
self.cv.create_image(0, 0, image=self.top_window_back_img, anchor=NW)
self.var_data_dict = {}
self.init_window()
if self.type == "update":
self.load_fractal_data()
def load_fractal_data(self):
fractal = DbUtil.query_fractal_by_id(self.fractal_id).iloc[0]
self.fractal_name.insert(0, str(fractal["name"]))
self.fractal_e_name.insert(0, str(fractal["e_name"]))
self.basic_pattern.insert(0.0, "\n".join(str(fractal["basic_pattern"]).split("\n")[:-1]))
self.function_code.insert(0.0, "\n".join(str(fractal["function_code"]).split("\n")[:-1]))
self.basic_execute_function.insert(0, str(fractal["basic_pattern"]).split("\n")[-1])
self.function_code_execute_function.insert(0, str(fractal["function_code"]).split("\n")[-1])
fractal_var = DbUtil.query_fractal_var_by_id(self.fractal_id)
for i in fractal_var.itertuples(index=False):
self.var_tree.insert("end", f"{i[2]} : {i[0]} = {i[1]}")
def create_label(self, x, y, img, label_text, entry_width=200):
self.cv.create_image(x, y, image=img, anchor=NW)
self.cv.create_text(x + self.label_width / 2, y + self.label_height / 2, text=label_text, font=("黑体", 12),
fill="black")
entry = Entry(self.cv, font=("Arial", 18, "bold"))
entry.place(x=x + self.label_width, y=y, width=entry_width, height=40, anchor=NW)
return entry
def add_var(self):
"""
todo: 添加一个变量
:return:
"""
fractal_comment = self.fractal_comment.get()
fractal_var_name = self.fractal_var_name.get()
fractal_var_value = self.fractal_var_value.get()
if fractal_var_name.strip() == "" and fractal_var_value.strip() == "" and fractal_comment.strip() == "":
messagebox.showwarning("提示", "变量名称,变量注释和变量值不能为空!")
return
if fractal_var_name in self.var_data_dict:
messagebox.showerror("提示", "该变量已经存在!")
self.fractal_comment.delete(0, "end"), self.fractal_var_name.delete(0, "end"), self.fractal_var_value.delete(0, "end")
return
self.var_data_dict[fractal_var_name] = (fractal_comment, fractal_var_value)
self.var_tree.insert("end", f"{fractal_comment} : {fractal_var_name} = {fractal_var_value}")
self.fractal_comment.delete(0, "end"), self.fractal_var_name.delete(0, "end"), self.fractal_var_value.delete(0, "end")
def save(self):
fractal_name = self.fractal_name.get()
fractal_e_name = self.fractal_e_name.get()
basic_execute_function = self.basic_execute_function.get()
function_code_execute_function = self.function_code_execute_function.get()
function_code = self.function_code.get(0.0, "end")
basic_pattern = self.basic_pattern.get(0.0, "end")
if fractal_name.strip() == "" \
and fractal_e_name == "" \
and basic_execute_function.strip() == ""\
and basic_pattern.strip() == ""\
and function_code.strip() == ""\
and function_code_execute_function.strip() == "":
messagebox.showwarning("提示", "值不能为空!")
return
function_code = function_code + "\n" + function_code_execute_function
basic_pattern = basic_pattern + "\n" + basic_execute_function
if self.type == "update":
DbUtil.update_to_fractal(self.fractal_id, fractal_name, fractal_e_name, basic_pattern, function_code)
for key, data in self.var_data_dict.items():
DbUtil.insert_to_var(key, data[1], data[0], self.fractal_id)
self.master.master.message.show_message("更新成功!")
else:
id = DbUtil.insert_to_fractal(fractal_name, fractal_e_name, basic_pattern, function_code)
for key, data in self.var_data_dict.items():
DbUtil.insert_to_var(key, data[1], data[0], id)
self.master.master.message.show_message("添加成功!")
self.destroy()
self.master.master.flush()
def init_window(self):
self.label_img = ImageTk.PhotoImage(
Image.open("./images/文字背景@3x.png").resize((self.label_width, self.label_height)))
self.fractal_name = self.create_label(50, 30, self.label_img, "分形名称")
self.fractal_e_name = self.create_label(50, 30 + self.label_height + 15, self.label_img, "分形英文名称")
self.fractal_comment = self.create_label(50, 30 + (self.label_height + 15) * 2, self.label_img, "变量注释")
self.fractal_var_name = self.create_label(50, 30 + (self.label_height + 15) * 3, self.label_img, "变量名称")
self.fractal_var_value = self.create_label(50, 30 + (self.label_height + 15) * 4, self.label_img, "变量值")
self.basic_execute_function = self.create_label(50, 30 + (self.label_height + 15) * 5, self.label_img, "基本图案调用函数")
self.function_code_execute_function = self.create_label(50 + 15 + self.label_width + 300 + 30, 30 + (self.label_height + 15) * 5, self.label_img, "分形树调用函数", entry_width=250)
Button(self.cv, image=self.add_var_img, command=self.add_var, bd=0, relief="solid", bg="#f7f7f7",
highlightthickness=0, ).place(x=50 + 15 + self.label_width + 200, y=30 + (self.label_height + 15) * 4, width=100, height=self.label_height, anchor=NW)
Button(self.cv, image=self.save_img if self.type == "add" else self.update_img, command=self.save, bd=0, relief="solid", bg="#f7f7f7",
highlightthickness=0, ).place(x=50 + 15 + self.label_width + 200, y=30 + (self.label_height + 15) * 7 - 15 + 300 - self.label_height, width=100, height=self.label_height, anchor=NW)
list_frame = Frame(self.cv)
list_frame.place(x=50 + 15 + self.label_width + 300 + 30, y=30, height=(self.label_height + 15) * 5 - 15, width=400)
self.var_tree = Listbox(list_frame, font=("Arial", 14), bg="#bce7f7", highlightthickness=0, highlightcolor="#bce7f7")
self.var_tree.pack(side="left", fill="both", expand=True)
scrollbar = Scrollbar(list_frame, command=self.var_tree.yview)
scrollbar.pack(side="right", fill="y")
self.var_tree.config(yscrollcommand=scrollbar.set)
self.basic_label_image = ImageTk.PhotoImage(Image.open("./images/文字背景@3x.png").resize((self.label_width + 200, 30)))
self.cv.create_image(50, (self.label_height + 15) * 7 - 15, image=self.basic_label_image, anchor=NW)
self.cv.create_text(50 + (self.label_width + 200) / 2, (self.label_height + 15) * 7, text="基本图案绘制函数", font=("黑体", 14))
self.basic_pattern = Text(self.cv, font=("Arial", 14), bg="#bce7f7", highlightthickness=0,)
self.basic_pattern.place(x=50, y=(self.label_height + 15) * 7 + 15, width=self.label_width + 200, height=300)
self.function_code_label_image = ImageTk.PhotoImage(Image.open("./images/文字背景@3x.png").resize((400, 30)))
self.cv.create_image(50 + 15 + self.label_width + 300 + 30, (self.label_height + 15) * 7 - 15, image=self.function_code_label_image, anchor=NW)
self.cv.create_text(50 + 15 + self.label_width + 300 + 30 + 400 / 2, (self.label_height + 15) * 7, text="分形树绘制函数",
font=("黑体", 14))
self.function_code = Text(self.cv, font=("Arial", 14), bg="#bce7f7", highlightthickness=0, )
self.function_code.place(x=50 + 15 + self.label_width + 300 + 30, y=(self.label_height + 15) * 7 + 15, width=400, height=300)
class SelectFractalFrame(Frame):
# todo: 右上方分形图案单选框类
def __init__(self, master, *args, ** kwargs):
super().__init__(master, *args, **kwargs)
self.db = DbUtil()
self.width = int(self.cget("width"))
self.height = int(self.cget("height"))
self.img = ImageTk.PhotoImage(Image.open("./images/上部背景@3x.png").resize(
(int(self.width), self.height)))
Label(self, width=self.width, height=self.height, image=self.img).place(x=0, y=0, anchor=NW)
Label(self, text="分形图案类型", font=("黑体", 14, "bold"), bg="#f7f7f7", ).place(x=10, y=10)
self.button_img = ImageTk.PhotoImage(Image.open("./images/新增分形图案类型@3x.png").resize((120, 36)))
Button(self, image=self.button_img, bd=0, relief="solid", bg="#f7f7f7",
highlightthickness=0, command=self.add_fractal_tree).place(x=280, y=8)
self.update_button_img = ImageTk.PhotoImage(Image.open("./images/修改分形图案@3x.png").resize((120, 36)))
Button(self, image=self.update_button_img, bd=0, relief="solid", bg="#f7f7f7",
highlightthickness=0, command=self.update_fractal_tree).place(x=150, y=8)
self.select_frame = Frame(self, width=self.width, height=self.height * 0.8, bg="#f7f7f7")
self.select_frame.place(x=0, y=self.height * 0.2)
self.create_select_menu()
def add_fractal_tree(self):
screen_width = root.winfo_screenwidth() # winfo方法来获取当前电脑屏幕大小
screen_height = root.winfo_screenheight()
x, y = int(screen_width - screen_width * 0.5) // 2, int(screen_height - screen_height * 0.6) // 2
top_window = AddFractal(self, "add", width=screen_width * 0.5, height=screen_height * 0.7)
top_window.geometry(f'{int(screen_width * 0.5)}x{int(screen_height * 0.7)}+{x}+{y}')
top_window.mainloop()
def update_fractal_tree(self):
screen_width = root.winfo_screenwidth() # winfo方法来获取当前电脑屏幕大小
screen_height = root.winfo_screenheight()
x, y = int(screen_width - screen_width * 0.5) // 2, int(screen_height - screen_height * 0.6) // 2
top_window = AddFractal(self, "update", width=screen_width * 0.5, height=screen_height * 0.7, fractal_id=self.master.chose_fractal.get())
top_window.geometry(f'{int(screen_width * 0.5)}x{int(screen_height * 0.7)}+{x}+{y}')
top_window.mainloop()
def create_select_menu(self):
# todo: 创建分形图案单选框
data_frame = self.db.execute("select * from fractal")
yscro = Scrollbar(self.select_frame, orient=VERTICAL)
yscro.place(x=self.width - 20, y=0, height=self.height * 0.8, width=20, anchor='nw')
canvas = Canvas(self.select_frame, width=self.width - 20, height=self.height * 0.8, bg="#f7f7f7")
canvas.place(x=0, y=0, anchor='nw')
f2 = Frame(canvas, bg="#f7f7f7", width=self.width * 0.8, height=self.height * 0.8)
canvas.create_window((0, 0), window=f2, anchor=NW)
self.master.chose_fractal = IntVar()
self.master.chose_fractal.set(data_frame.loc[0:]["id"].tolist()[0])
for data in data_frame.itertuples(index=False):
f_id, name, e_name, basic_pattern, function_code = data[0], data[1], data[2], data[3], data[4]
Radiobutton(f2, text=f"{name} {e_name}", value=f_id, command=lambda message=f"{name} {e_name}": self.master.update_select(message),
variable=self.master.chose_fractal, font=("", 18), bg="#f7f7f7").pack(ipadx=10, anchor="w")
canvas.update()
canvas.config(scrollregion=canvas.bbox("all"), yscrollcommand=yscro.set) # 设置画布的滚动区域
yscro.config(command=canvas.yview)
class FormFractalFrame(Frame):
# todo: 右下方变量填写类
def __init__(self, master, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.db = DbUtil()
self.width = int(self.cget("width"))
self.height = int(self.cget("height"))
self.var_dict = {}
self.img = ImageTk.PhotoImage(Image.open("./images/上部背景@3x.png").resize(
(int(self.width), self.height)))
Label(self, width=self.width, height=self.height, image=self.img).place(x=0, y=0, anchor=NW)
Label(self, text="分形参数设置", font=("黑体", 14, "bold"), bg="#f7f7f7", ).place(x=10, y=10)
self.create_form()
self.button_img = ImageTk.PhotoImage(Image.open("./images/基本图案绘制@3x.png").resize((90, 36)))
Button(self, image=self.button_img, bd=0, relief="solid", bg="#f7f7f7",
highlightthickness=0, command=self.master.basic_tree_canvas.draw_basic_tree).place(x=10, y=self.height - 50)
self.button2_img = ImageTk.PhotoImage(Image.open("./images/绘制参数更新@3x.png").resize((90, 36)))
Button(self, image=self.button2_img, bd=0, relief="solid", bg="#f7f7f7",
highlightthickness=0, command=self.update_fractal_var).place(x=100 + 5, y=self.height - 50)
self.button3_img = ImageTk.PhotoImage(Image.open("./images/绘制@3x.png").resize((70, 36)))
Button(self, image=self.button3_img, bd=0, relief="solid", bg="#f7f7f7",
highlightthickness=0, command=self.master.fractal_tree_canvas.draw_fractal_tree).place(x=100 * 2 + 5, y=self.height - 50)
self.button4_img = ImageTk.PhotoImage(Image.open("./images/删除图案@3x.png").resize((90, 36)))
Button(self, image=self.button4_img, bd=0, relief="solid", bg="#f7f7f7",
highlightthickness=0, command=self.delete_fractal).place(x=95 * 3, y=self.height - 50)
def delete_fractal(self):
"""
删除分形树
:return:
"""
result = messagebox.askquestion("确认框", "您确定要执行此操作吗?")
if not result == "yes":
return
fractal_id = self.master.chose_fractal.get()
DbUtil.delete_fractal(fractal_id)
self.master.flush()
self.master.message.show_message("删除成功!")
def update_fractal_var(self):
# todo: 绘制参数更新
try:
for key, value in self.var_dict.items():
sql = "update fractal_var set value='{}' where fractal_id={} and name='{}'".format(value.get(), self.master.chose_fractal.get(), key)
self.db.update(sql)
self.master.message.show_message("参数更新成功!")
except Exception as E:
self.master.message.show_message(f"{E}", "red")
def create_form(self):
# todo: 分形图案变量生成
data_frame = self.db.query_fractal_var_by_id(self.master.chose_fractal.get())
self.select_frame = Frame(self, width=self.width, height=self.height * 0.6, bg="#f7f7f7")
self.select_frame.place(x=0, y=self.height * 0.2)
yscro = Scrollbar(self.select_frame, orient=VERTICAL)
yscro.place(x=self.width - 20, y=0, height=self.height * 0.6, width=20, anchor='nw')
canvas = Canvas(self.select_frame, width=self.width - 20, height=self.height * 0.6, bg="#f7f7f7")
canvas.place(x=0, y=0, anchor='nw')
f2 = Frame(canvas, bg="#f7f7f7", width=self.width * 0.8, height=self.height * 0.6)
canvas.create_window((0, 0), window=f2, anchor=NW)
self.var_dict = {}
for data in data_frame.itertuples():
index, name, value, comment, value_type = data[0], data[1], data[2], data[3], data[4]
Label(f2, text=f"{comment}{name}=", width=20, font=("黑体", 14, "bold"), anchor=W, bg="#f7f7f7").grid(row=index, column=0, padx=10, pady=10)
self.var_dict[name] = Entry(f2, font=("黑体", 14, "bold"))
self.var_dict[name].insert(0, value)
self.var_dict[name].grid(row=index, column=1, pady=10)
self.master.message.show_message(f"\t{comment}{name} = {value}")
canvas.update()
canvas.config(scrollregion=canvas.bbox("all"), yscrollcommand=yscro.set) # 设置画布的滚动区域
yscro.config(command=canvas.yview)
class BasicTree(Canvas):
# todo: 基本图案绘制画布类
def __init__(self, master, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.db = DbUtil()
self.width = int(self.cget("width"))
self.height = int(self.cget("height"))
self.background_img = ImageTk.PhotoImage(Image.open("./images/全览图@3x.png").resize((self.width + 20, self.height + 20)))
self.create_image(-5, -5, image=self.background_img, anchor=NW)
def draw_basic_tree(self):
# todo: 绘制基本图案
self.delete("all")
data_frame = self.db.query_fractal_by_id(self.master.chose_fractal.get())
params = {
"canvas": self
}
try:
exec(data_frame["basic_pattern"].tolist()[0], params)
self.master.message.show_message(f"基本图案绘制成功!")
except Exception as E:
self.master.message.show_message(f"{E}", color="red")
class FractalTreeCanvas(Canvas):
# todo: 绘制分形树画布
def __init__(self, master, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.db = DbUtil()
self.width = int(self.cget("width"))
self.height = int(self.cget("height"))
def draw_fractal_tree(self):
# todo: 绘制分形树
try:
self.delete("all")
data_frame = self.db.query_fractal_by_id(self.master.chose_fractal.get())
fractal_var = self.db.query_fractal_var_by_id(self.master.chose_fractal.get())
params = {fractal_var["name"].tolist()[i]: eval(fractal_var["value"].tolist()[i]) for i in range(len(fractal_var["name"].tolist()))}
params["canvas"] = self
params["math"] = math
params["sleep"] = sleep
exec(data_frame["function_code"].tolist()[0], params)
self.master.message.show_message("分形树绘制成功!")
except Exception as E:
self.master.message.show_message(f"{E}", "red")
class FractalTree(Canvas):
def __init__(self, master, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.db = DbUtil()
self.width = int(self.cget("width"))
self.height = int(self.cget("height"))
self.background_image = ImageTk.PhotoImage(Image.open("./images/大背景@3x.jpg").resize((self.width, self.height)))
self.create_image(0, 0, image=self.background_image, anchor=NW)
self.chose_fractal = 1
self.function_code = ""
self.fractal_var = {}
self.init_window()
def update_select(self, message):
# todo: 切换分形图案
self.message.show_message(f"选择了{message},参数如下:")
self.form_fractal_frame.create_form()
def flush(self):
self.select_fractal_frame.create_select_menu()
self.form_fractal_frame.create_form()
def init_window(self):
"""
初始化窗口,创建窗口并布局
:return:
"""
# 创建下方消息显示框
message_frame = Frame(self, width=self.width - 60, height=self.height * 0.2)
message_frame.place(x=15, y=self.height * 0.8 + 15, anchor=NW)
self.message = Message(message_frame, width=self.width - 60, height=self.height * 0.2 - 30)
self.message.pack(anchor=NW)
self.message.configure(bg="#85bbd1")
# 分形树画布
self.fractal_tree_canvas = FractalTreeCanvas(self, width=self.width * 0.73 - 10, height=self.height * 0.8 + 12, highlightthickness=0, bg="#b5e6f5")
self.fractal_tree_canvas.place(x=0, y=0, anchor=NW)
# 基本图形绘制框
self.basic_tree_canvas = BasicTree(self, width=150, height=150, bg="#e0eaf5", bd=0)
self.basic_tree_canvas.place(x=15, y=self.height * 0.8 - 150, anchor=NW)
# 创建左上方分形图案选择框
self.select_fractal_frame = SelectFractalFrame(self, width=self.width * 0.27 - 10, height=int((self.height * 0.8) / 2) - 10)
self.select_fractal_frame.place(x=self.width * 0.73, y=10, anchor=NW)
# 创建左下方输入框
self.form_fractal_frame = FormFractalFrame(self, width=self.width * 0.27 - 10, height=int((self.height * 0.8) / 2))
self.form_fractal_frame.place(x=self.width * 0.73, y=self.height * 0.8 / 2 + 10, anchor=NW)
if __name__ == '__main__':
# 创建主窗口
root = Tk()
root.title('分形树')
screen_width = root.winfo_screenwidth() # winfo方法来获取当前电脑屏幕大小
screen_height = root.winfo_screenheight()
root_attr = {
"width": screen_width * 0.8,
"height": screen_height * 0.8,
}
size = '%dx%d+%d+%d' % (root_attr['width'], root_attr['height'], (screen_width - root_attr['width']) / 2,
(screen_height - root_attr['height']) / 2 - 30)
root.geometry(size)
tree = FractalTree(root, width=root_attr["width"], height=root_attr["height"])
tree.place(x=0, y=0, anchor=NW)
root.mainloop()