|
|
# -*- coding: utf-8 -*-
|
|
|
# Time : 2023/8/9 10:20
|
|
|
# Author : lirunsheng
|
|
|
# User : l'r's
|
|
|
# Software: PyCharm
|
|
|
# File : X5.py
|
|
|
|
|
|
# -*- encoding: utf-8 -*-
|
|
|
"""
|
|
|
@Author: packy945
|
|
|
@FileName: main.py
|
|
|
@DateTime: 2023/5/30 15:29
|
|
|
@SoftWare: PyCharm
|
|
|
"""
|
|
|
import random
|
|
|
import re
|
|
|
from tkinter import messagebox
|
|
|
|
|
|
import pandas as pd
|
|
|
from sympy import sympify, SympifyError
|
|
|
import sys
|
|
|
from fitting import *
|
|
|
import numpy as np
|
|
|
import data as gl_data
|
|
|
import input
|
|
|
import tkinter as tk
|
|
|
from tkinter import ttk
|
|
|
from tkinter import *
|
|
|
from screeninfo import get_monitors
|
|
|
import os
|
|
|
from PIL import ImageTk, Image
|
|
|
import tkinter.filedialog # 注意次数要将文件对话框导入
|
|
|
# from demo1 import Addfunc
|
|
|
from newly_added.formula import *
|
|
|
from scipy.optimize import leastsq
|
|
|
|
|
|
global Q_root,F_root
|
|
|
global root_window
|
|
|
global label1,label2,label3
|
|
|
|
|
|
|
|
|
# 创建弹出窗口
|
|
|
def creat_window(title):
|
|
|
top = tk.Toplevel(root_window)
|
|
|
top.geometry("300x350")
|
|
|
top.title(title)
|
|
|
return top
|
|
|
|
|
|
# 输入框
|
|
|
def create_input_box(top, text, value):
|
|
|
box_label = tk.Label(top, text=text)
|
|
|
box_label.pack(padx=10, pady=10)
|
|
|
box_size = tk.IntVar(top, value=value) # 创建一个IntVar对象,并设置默认值为3
|
|
|
box_size_entry = tk.Entry(top, textvariable=box_size) # 关联IntVar对象
|
|
|
box_size_entry.pack(padx=20, pady=20)
|
|
|
return box_size_entry
|
|
|
|
|
|
def check_formula_syntax(formula):
|
|
|
try:
|
|
|
sympify(formula)
|
|
|
return True
|
|
|
except SympifyError:
|
|
|
return False
|
|
|
def create_func(code_str):
|
|
|
# 创建一个空的命名空间
|
|
|
namespace = {}
|
|
|
# 使用exec函数执行字符串代码,并指定命名空间为locals
|
|
|
exec(code_str, globals(), namespace)
|
|
|
# 返回命名空间中的函数对象
|
|
|
return namespace['func']
|
|
|
|
|
|
def fitting(letters,result):
|
|
|
code_str = '''
|
|
|
def func({}):
|
|
|
return {}
|
|
|
'''.format(letters,result)
|
|
|
return code_str
|
|
|
|
|
|
def save(result1, letters, result , result2):
|
|
|
gl_data.INDEX = len(gl_data.FITT_SAVE['no'])
|
|
|
gl_data.FITT_SAVE['no'][gl_data.INDEX] = gl_data.INDEX
|
|
|
gl_data.FITT_SAVE['name'][gl_data.INDEX] = result1
|
|
|
gl_data.FITT_SAVE['variable'][gl_data.INDEX] = letters
|
|
|
gl_data.FITT_SAVE['function'][gl_data.INDEX] = result
|
|
|
gl_data.FITT_SAVE['demo'][gl_data.INDEX] = result2
|
|
|
file_path = 'functions_new.xlsx'#设置路径
|
|
|
# 将字典转换为DataFrame
|
|
|
df = pd.DataFrame(gl_data.FITT_SAVE)
|
|
|
# 将DataFrame保存为Excel文件
|
|
|
df.to_excel(file_path, index=False)
|
|
|
|
|
|
def read_fitting():
|
|
|
file_path = 'functions_new.xlsx' # 设置路径
|
|
|
df = pd.read_excel(io=file_path, header=0) # 设置表格
|
|
|
gl_data.FITT_SAVE = df.to_dict()
|
|
|
|
|
|
def create_func(code_str):
|
|
|
# 创建一个空的命名空间
|
|
|
namespace = {}
|
|
|
# 使用exec函数执行字符串代码,并指定命名空间为locals
|
|
|
exec(code_str, globals(), namespace)
|
|
|
# 返回命名空间中的函数对象
|
|
|
return namespace['func']
|
|
|
|
|
|
def addfunc():
|
|
|
top = creat_window('新增拟合函数') # 创建弹出窗口
|
|
|
function_entry = create_input_box(top, "拟合函数名称:", '') # 创建一个输入框,获取拟合函数名称
|
|
|
math_entry = create_input_box(top, "数学式:", '') # 创建一个输入框,获取数学式
|
|
|
def get_input(): # 创建
|
|
|
# 获取输入框的内容
|
|
|
result1 = function_entry.get()
|
|
|
result2 = math_entry.get()
|
|
|
if result1 and result2:
|
|
|
if check_formula_syntax(result2):
|
|
|
top.destroy() # 关闭窗口
|
|
|
letters, result = expression_output(result2)
|
|
|
save(result1, letters, result, result2)
|
|
|
gl_data.Xian_index = gl_data.INDEX
|
|
|
f_button()
|
|
|
else:
|
|
|
messagebox.showinfo('提示', '你输入的数学公式错误!')
|
|
|
else:
|
|
|
messagebox.showinfo('提示','你未输入的完成!')
|
|
|
button = tk.Button(top, text="确定", command=get_input)
|
|
|
button.pack()
|
|
|
|
|
|
def jis():
|
|
|
global screen_size
|
|
|
# 获取当前屏幕的宽度和高度
|
|
|
monitors = get_monitors()
|
|
|
screen_width = monitors[0].width
|
|
|
# 计算按钮的宽度和高度
|
|
|
button_width = int(screen_width * 0.85)
|
|
|
# 打印按钮的宽度和高度
|
|
|
screen_size = round(button_width*0.9/900, 1)
|
|
|
gl_data.MAGNIDICATION = screen_size
|
|
|
read_fitting()
|
|
|
|
|
|
def element1(path):
|
|
|
# print(path)
|
|
|
# 加载图像并创建一个 PhotoImage 对象
|
|
|
image = tk.PhotoImage(file=path)
|
|
|
# 保存图片的引用,防止被垃圾回收
|
|
|
root_window.image = image
|
|
|
return image
|
|
|
|
|
|
def element(path, width, height):
|
|
|
# 加载图元对应的图片文件
|
|
|
img = Image.open(path)
|
|
|
# # 使用resize方法调整图片
|
|
|
img = img.resize((width, height))
|
|
|
# 把Image对象转换成PhotoImage对象
|
|
|
img = ImageTk.PhotoImage(img)
|
|
|
# 保存图片的引用,防止被垃圾回收
|
|
|
root_window.img = img
|
|
|
return img
|
|
|
|
|
|
def window():
|
|
|
global root_window
|
|
|
global label1, label2, label3
|
|
|
root_window = Tk()
|
|
|
root_window.title('函数拟合')
|
|
|
width, height = int(900*screen_size), int(560*screen_size)
|
|
|
root_window.geometry(str(width)+'x'+str(height)) # 设置窗口大小:宽x高,注,此处不能为 "*",必须使用 "x"
|
|
|
# 设置主窗口的背景颜色,颜色值可以是英文单词,或者颜色值的16进制数,除此之外还可以使用Tk内置的颜色常量
|
|
|
img_path = ["background/add.png", "background/下方输入框.png", "background/右侧未选中.png", "background/右侧背景.png",
|
|
|
"background/右侧选中.png","background/大背景.png", "background/导航拦.png", "background/导航输入框.png",
|
|
|
"background/小直线.png", "background/手动输入数据集.png", "background/拟合.png", "background/新增拟合曲线类型.png",
|
|
|
"background/显示数据集与曲线.png", "background/未选中.png", "background/生成数据集.png", "background/矩形.png",
|
|
|
"background/背景图片.png", "background/装载.png", "background/选中.png", "background/显示数据集.png",
|
|
|
"background/img.png"
|
|
|
]
|
|
|
global list_image
|
|
|
list_image = []
|
|
|
for i in range(len(img_path)):
|
|
|
if i in [17, 14, 19, 10, 12]:
|
|
|
list_image.append(element(img_path[i], 110, 80))
|
|
|
elif i == 16:
|
|
|
list_image.append(element(img_path[i], width, height))
|
|
|
elif i in [11, 9]:
|
|
|
list_image.append(element(img_path[i], 240, 80))
|
|
|
else:
|
|
|
list_image.append(element1(img_path[i]))
|
|
|
# root_window["background"] = "#87ceeb"
|
|
|
canvas = tk.Canvas(root_window, width=width-10, height=int(560*screen_size)-10)
|
|
|
canvas.place(x=0, y=0)
|
|
|
canvas.create_image(0, 0, image=list_image[16], anchor=tk.NW)
|
|
|
root_window.resizable(0, 0) # 防止用户调整尺寸
|
|
|
canvas.create_text(int(40*screen_size), int(26*screen_size), text='样本数据\n集文件', font='Arial 14', fill='black')
|
|
|
label3 = tk.Label(root_window, text="", font=('Times', 12), bg="#ADD8E6", fg="black",
|
|
|
width=50, height=3, padx=0, pady=0, borderwidth=0, relief="ridge", highlightcolor="blue")
|
|
|
label3.place(x=int(122*screen_size), y=int(10*screen_size))
|
|
|
# 使用按钮控件调用函数
|
|
|
tk.Button(root_window, image=list_image[17], relief=tk.FLAT, bd=0, command=lambda: askfile()).place(x=int(490*screen_size), y=int(12*screen_size))
|
|
|
canvas.create_text(int(610*screen_size), int(40 * screen_size), text='拟合曲线类型', font='Arial 14', fill='black')
|
|
|
gl_data.Canvas2 = tk.Canvas(root_window, bg='white', width=int(550*screen_size), height=int(330*screen_size))
|
|
|
gl_data.Canvas2.place( x=int(4*screen_size), y=int(60*screen_size))
|
|
|
|
|
|
canvas.create_text(int(60*screen_size), int(490*screen_size),text="结果输出:", font='Arial 16', fill='black')
|
|
|
|
|
|
# 定义一个处理文件的相关函数
|
|
|
def askfile():
|
|
|
# 从本地选择一个文件,并返回文件的路径
|
|
|
filename = tkinter.filedialog.askopenfilename()
|
|
|
if filename != '':#若选中了一个文件,则对文件进行读取
|
|
|
label3.config(text=filename)#显示文件路径
|
|
|
read_sample_data(filename)#将文件读取并存到sampleData中
|
|
|
# print_sample_data(filename)#将文件读取并逐行输出
|
|
|
selfdata_show(gl_data.X, gl_data.Y, gl_data.LOW, gl_data.HIGH)
|
|
|
else:#若未选择文件,则显示为空
|
|
|
label3.config(text='')
|
|
|
|
|
|
def print_sample_data(file_path):#打开对应文件
|
|
|
with open(file_path, 'r') as file:
|
|
|
for line in file:#逐行读取文件
|
|
|
line = line.strip('\n')#移除换行符
|
|
|
sx, sy = line.split(' ')#以空格分割x,y
|
|
|
print(f'sx: {float(sx)}, sy: {float(sy)}')#将sx、sy转换为浮点数并打印
|
|
|
|
|
|
def read_sample_data(file_path):
|
|
|
x, y = [], []#初始化x,y
|
|
|
with open(file_path, 'r') as file:
|
|
|
for line in file:#逐行读文件
|
|
|
line = line.strip('\n')#移除换行符
|
|
|
sx, sy = line.split(' ')#以空格分割x,y
|
|
|
x.append(float(sx))#将sx转换为浮点数并加入数组
|
|
|
y.append(float(sy))#将sy转换为浮点数并加入数组
|
|
|
gl_data.X, gl_data.Y = np.array(x), np.array(y)#x,y数组转为array并赋值给全局变量
|
|
|
|
|
|
def buttons():
|
|
|
# 随机生成样本点并显示
|
|
|
b_dot = tk.Button(root_window, image=list_image[14], relief=tk.FLAT, bd=0, command=lambda: generate_and_plot_sample_data(gl_data.LOW, gl_data.HIGH))
|
|
|
b_dot.place(x=int(435*screen_size), y=int(410*screen_size))
|
|
|
# 显示当前样本点
|
|
|
b_show = tk.Button(root_window, image=list_image[19], relief=tk.FLAT, bd=0, command=lambda: selfdata_show(gl_data.X, gl_data.Y, gl_data.LOW, gl_data.HIGH))
|
|
|
b_show.place(x=int(515*screen_size), y=int(410*screen_size))
|
|
|
# 显示数据集与曲线
|
|
|
b_line = tk.Button(root_window, image=list_image[12], relief=tk.FLAT, bd=0, command=lambda: draw_dots_and_line(gl_data.Xian_index, gl_data.LOW, gl_data.HIGH,
|
|
|
gl_data.X, gl_data.Y))
|
|
|
b_line.place(x=int(595*screen_size), y=int(410*screen_size))
|
|
|
# 手动输入数据集
|
|
|
b_input = tk.Button(root_window, image=list_image[9], relief=tk.FLAT, bd=0, command=lambda: input.input_num(root_window))
|
|
|
b_input.place(x=int(675*screen_size), y=int(410*screen_size))
|
|
|
# 拟合并输出拟合结果
|
|
|
b_fit = tk.Button(root_window, image=list_image[10], relief=tk.FLAT, bd=0, command=lambda: fit_data(gl_data.Xian_index, gl_data.X, gl_data.Y))
|
|
|
b_fit.place(x=int(821*screen_size), y=int(410*screen_size))
|
|
|
|
|
|
def show_fit():
|
|
|
sout = str(gl_data.Out)
|
|
|
ans = tk.Label(root_window, text=sout, font=("微软雅黑", 14)
|
|
|
, anchor=W, justify='left')
|
|
|
ans.place(x=int(120*screen_size), y=int(480*screen_size), width=int(760*screen_size), height=100)
|
|
|
print(sout)
|
|
|
|
|
|
def fit_data(xian_index, sx, sy):
|
|
|
if gl_data.Quadrant:
|
|
|
x = sx.tolist()
|
|
|
y = sy.tolist()
|
|
|
negative_x = [i for i, num in enumerate(x) if num < 0]
|
|
|
negative_y = [i for i, num in enumerate(y) if num < 0]
|
|
|
negative = list(set(negative_x + negative_y))
|
|
|
for index in range(len(negative)):
|
|
|
# print(negative[-index-1])
|
|
|
x.pop(negative[-index-1])
|
|
|
y.pop(negative[-index-1])
|
|
|
sx = np.array(x)
|
|
|
sy = np.array(y)
|
|
|
letters, result = gl_data.FITT_SAVE['variable'][xian_index], gl_data.FITT_SAVE['function'][xian_index]
|
|
|
code_str = fitting(letters, result)
|
|
|
func = create_func(code_str) # 获取当前函数func
|
|
|
popt, pcov = curve_fit(func, sx, sy) # 用curve_fit来对点进行拟合
|
|
|
yvals_pow = func(gl_data.X, *popt)
|
|
|
rr = gl_data.goodness_of_fit(yvals_pow, gl_data.Y)# 计算本次拟合的R*R值,用于表示拟合优度
|
|
|
# 输出拟合后的各个参数值
|
|
|
ans = '\n函数系数:F(x) = '
|
|
|
letter = str(letters[2:]).split(',')
|
|
|
pattern = re.compile('|'.join(letter))
|
|
|
s = pattern.sub('{:.2f}', gl_data.FITT_SAVE['demo'][xian_index])
|
|
|
ans += str(s.format(*popt))
|
|
|
gl_data.Out = '函数形式:' + gl_data.FITT_SAVE['name'][xian_index] + ' '
|
|
|
gl_data.Out += gl_data.FITT_SAVE['demo'][xian_index]
|
|
|
gl_data.Out += ans
|
|
|
gl_data.Out += '\n拟合优度(R\u00b2):' + str(round(rr, 5))
|
|
|
show_fit()# 显示函数信息到输出框
|
|
|
|
|
|
def change_Q(no):
|
|
|
gl_data.Quadrant = no #更改全局变量的象限显示
|
|
|
if no:#若为一象限,则修改显示下限为0
|
|
|
gl_data.LOW = 0
|
|
|
else:#若为四象限,则修改显示下限为-gl_data.maxV
|
|
|
gl_data.LOW = -gl_data.MAXV
|
|
|
q_button()#更新象限显示面板
|
|
|
|
|
|
def q_button():
|
|
|
r = 7.5
|
|
|
rr = 2.5
|
|
|
for widget in Q_root.winfo_children():
|
|
|
widget.destroy()
|
|
|
q_cv = tk.Canvas(Q_root, width=int(400*screen_size), height=int(50*screen_size))
|
|
|
q_cv.place(x=0, y=0)
|
|
|
# q_cv.create_image(0, 0, image=list_image[20], anchor=tk.NW)
|
|
|
l = tk.Label(Q_root, text='坐标轴', bd=0, font=("微软雅黑", 16), anchor=W)
|
|
|
l.place(x=20, y=0, width=int(80*screen_size), height=int(50*screen_size),)
|
|
|
# 四象限按钮
|
|
|
b1 = tk.Button(Q_root, text='四象限', bd=0, font=("微软雅黑", 16)
|
|
|
, command=lambda: change_Q(0), anchor=W)
|
|
|
b1.place(x=int(170*screen_size), y=0, width=int(80*screen_size), height=int(50*screen_size),)
|
|
|
# 一象限按钮
|
|
|
b2 = tk.Button(Q_root, text='一象限', bd=0, font=("微软雅黑", 16)
|
|
|
, command=lambda: change_Q(1), anchor=W)
|
|
|
b2.place(x=int(320*screen_size), y=0, width=int(80*screen_size), height=int(50*screen_size),)
|
|
|
# # 绘制标记框
|
|
|
q_cv.create_image(int((145 - r)*screen_size), int((35 - r)*screen_size),
|
|
|
image=list_image[2])
|
|
|
q_cv.create_image(int((295 - r)*screen_size), int((35 - r)*screen_size),
|
|
|
image=list_image[2])
|
|
|
# 根据当前的象限选择值来填充标记框
|
|
|
if gl_data.Quadrant == 0:
|
|
|
q_cv.create_image(int((140 - rr)*screen_size), int((30 - rr)*screen_size),
|
|
|
image=list_image[18])
|
|
|
else:
|
|
|
q_cv.create_image(int((290 - rr)*screen_size), int((30 - rr)*screen_size),
|
|
|
image=list_image[18])
|
|
|
def change_f(no):
|
|
|
gl_data.Xian_index = no#设置全局函数编号为该函数
|
|
|
f_button()#重新绘制函数显示界面
|
|
|
|
|
|
def f_button():
|
|
|
r = 7.5 # 设置按钮大小
|
|
|
rr = 2.5 # 设置按钮大小
|
|
|
for widget in F_root.winfo_children():
|
|
|
widget.destroy() # 清空原有按钮
|
|
|
gl_data.INDEX = len(gl_data.FITT_SAVE['no'])
|
|
|
canvas = Canvas(F_root, width=int(320 * screen_size), height=int(270 * screen_size))
|
|
|
# # 将图像添加到 Canvas 组件中
|
|
|
canvas.pack(side="left", fill="both", expand=True)
|
|
|
scrollbar = Scrollbar(F_root, orient="vertical", command=canvas.yview)
|
|
|
scrollbar.pack(fill="y", side="right")
|
|
|
canvas.configure(yscrollcommand=scrollbar.set)
|
|
|
canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
|
|
|
if gl_data.INDEX - 10 <= 0:
|
|
|
result = 0
|
|
|
else:
|
|
|
result = gl_data.INDEX - 10
|
|
|
canvas_height = int(328 * screen_size) + result*50 # 或根据需要调整适当的高度增加值
|
|
|
# # 绘制矩形边框及底色
|
|
|
canvas.create_rectangle(2, 2, int(398 * screen_size), canvas_height, fill='#ADD8E6', outline="#0099ff")
|
|
|
# canvas.create_image(4, 4, image=list_image[3], anchor=tk.NW)
|
|
|
cur = 0 # 函数计数
|
|
|
for i in range(gl_data.INDEX): # 遍历函数库
|
|
|
if gl_data.FITT_SAVE['no'][i] == gl_data.Xian_index: # 若选择为当前函数则标记
|
|
|
# 在指定位置绘制图片
|
|
|
canvas.create_image(int((20 - rr) * screen_size), int((20 + 15 + cur * 30 - rr) * screen_size), image=list_image[4])
|
|
|
else:
|
|
|
# 在指定位置绘制图片
|
|
|
canvas.create_image(int((20 - rr) * screen_size), int((20 + 15 + cur * 30 - rr) * screen_size),
|
|
|
image=list_image[2])
|
|
|
# 绘制切换按钮,单击则将当前使用函数切换为该函数
|
|
|
button = tk.Button(F_root, text=gl_data.FITT_SAVE['name'][i] + ' ' + gl_data.FITT_SAVE['demo'][i], bd=0,
|
|
|
bg="#ADD8E6", font=("微软雅黑", 10),
|
|
|
command=lambda x=gl_data.FITT_SAVE['no'][i]: change_f(x), anchor=W)
|
|
|
# 将按钮放置在Canvas中
|
|
|
canvas.create_window(int(40 * screen_size), int((30 + cur * 30) * screen_size), window=button, anchor="w")
|
|
|
cur += 1 # 计数加一
|
|
|
canvas.configure(scrollregion=canvas.bbox("all"))
|
|
|
|
|
|
|
|
|
def close_window():
|
|
|
sys.exit()
|
|
|
|
|
|
def functional_formula(letter,result,decimals):
|
|
|
# 使用 zip() 函数将两个列表组合成元组的迭代器
|
|
|
pairs = zip(letter, decimals)
|
|
|
# 使用字典推导式构建字典
|
|
|
target = {key: str(value) for key, value in pairs}
|
|
|
# print(target)
|
|
|
# # 依次替换字符串中的元素
|
|
|
for key, value in target.items():
|
|
|
indices = [i for i, c in enumerate(result) if c == key]
|
|
|
for i in indices:
|
|
|
if (i + 1) == len(result) or result[i + 1] in ['*', '+', '-', '/', ')', '']:
|
|
|
result = result[0:i] + value + result[i + 1:]
|
|
|
return result
|
|
|
|
|
|
|
|
|
def make_func(letters,result):
|
|
|
# print(letters,result)
|
|
|
letter = str(letters).split(',')
|
|
|
n = len(letter)-1
|
|
|
decimals = [round(random.uniform(-10, 10), 1) for _ in range(n)]
|
|
|
target_result = functional_formula(letter[1:], result, decimals)
|
|
|
# 清除以前的值
|
|
|
entry3.delete(0, tk.END)
|
|
|
# 填入函数
|
|
|
entry3.insert(0, target_result)
|
|
|
code_str = fitting('x', target_result)
|
|
|
target_func = create_func(code_str) # 获取当前函数func
|
|
|
curve_func(target_func)
|
|
|
|
|
|
def curve_func(func):
|
|
|
# 绘制拟合结果
|
|
|
draw_axis(-100, 100, 20)
|
|
|
x_fit = np.linspace(-100, 100, 100)
|
|
|
y_fit = func(x_fit)
|
|
|
|
|
|
plt.plot(x_fit, y_fit, 'r-', label='拟合曲线')
|
|
|
plt.legend()
|
|
|
plt.xlabel('x')
|
|
|
plt.ylabel('y')
|
|
|
# plt.show()
|
|
|
plt.savefig('new_line.png')
|
|
|
# 清除当前图形状态
|
|
|
plt.clf()
|
|
|
show_image()
|
|
|
|
|
|
def show_image():
|
|
|
# 加载图像
|
|
|
image = Image.open("new_line.png")
|
|
|
image = image.resize((500, 500))
|
|
|
# 在画布上显示图像
|
|
|
image_tk = ImageTk.PhotoImage(image)
|
|
|
root_window.image_tk = image_tk
|
|
|
show_canvas.create_image(0, 0, anchor="nw", image=image_tk)
|
|
|
|
|
|
|
|
|
def add_func():
|
|
|
result1 = entry1.get()
|
|
|
result2 = entry2.get()
|
|
|
if result1 and result2:
|
|
|
if check_formula_syntax(result2):
|
|
|
letters, result = expression_output(result2)
|
|
|
if result == None:
|
|
|
messagebox.showinfo('提示', '你输入的数学公式错误!')
|
|
|
else:
|
|
|
make_func(letters,result)
|
|
|
else:
|
|
|
messagebox.showinfo('提示', '你输入的数学公式错误!')
|
|
|
else:
|
|
|
messagebox.showinfo('提示','你未输入的完成!')
|
|
|
|
|
|
def customized_curve():
|
|
|
result1 = entry2.get()
|
|
|
result2 = entry3.get()
|
|
|
if result1 and result2:
|
|
|
if check_formula_syntax(result1):
|
|
|
letters, result = expression_output(result1)
|
|
|
if result == None:
|
|
|
messagebox.showinfo('提示', '你输入的数学公式错误!')
|
|
|
else:
|
|
|
# 删除空格
|
|
|
result2 = result2.replace(' ', '')
|
|
|
# 使用正则表达式替换数字为空字符串
|
|
|
result3 = re.sub(r'[-]?\d+(\.\d+)?', '', result2)
|
|
|
letter = str(letters).split(',')
|
|
|
decimals = [1 for _ in range(len(letter)-1)]
|
|
|
result4 = functional_formula(letter[1:], result, decimals)
|
|
|
result4 = result4.replace('1', '')
|
|
|
result4 = re.sub(r'[-]?\d+(\.\d+)?', '', result4)
|
|
|
result4 = result4.replace(' ', '')
|
|
|
# print(result3,result4)
|
|
|
if result3 == result4:
|
|
|
code_str = fitting('x', result2)
|
|
|
func = create_func(code_str) # 获取当前函数func
|
|
|
curve_func(func)
|
|
|
else:
|
|
|
messagebox.showinfo('提示', '请检查你修改的函数是否与函数式相对应!')
|
|
|
def func_save():
|
|
|
result1 = entry1.get()
|
|
|
result2 = entry2.get()
|
|
|
if result1 and result2:
|
|
|
if check_formula_syntax(result2):
|
|
|
letters, result = expression_output(result2)
|
|
|
if result== None:
|
|
|
messagebox.showinfo('提示', '你输入的数学公式错误!')
|
|
|
else:
|
|
|
save(result1, letters, result, result2)
|
|
|
subwindow.destroy() # 关闭子页面
|
|
|
gl_data.Xian_index = gl_data.INDEX
|
|
|
f_button()
|
|
|
else:
|
|
|
messagebox.showinfo('提示', '你输入的数学公式错误!')
|
|
|
else:
|
|
|
messagebox.showinfo('提示', '你未输入的完成!')
|
|
|
|
|
|
|
|
|
def show_subwindow():
|
|
|
global subwindow
|
|
|
subwindow = tk.Toplevel(root_window)
|
|
|
subwindow.geometry('1000x500')
|
|
|
subwindow.title('新增拟合函数')
|
|
|
# 创建画布
|
|
|
global show_canvas
|
|
|
canvas_width = 1000
|
|
|
canvas_height = 500
|
|
|
canvas = Canvas(subwindow, width=canvas_width, height=canvas_height, bg="#ADD8E6")
|
|
|
canvas.pack()
|
|
|
show_canvas = Canvas(canvas, width=600, height=500, bg="white")
|
|
|
show_canvas.place(x=0, y=0)
|
|
|
global entry1, entry2, entry3
|
|
|
# 创建输入框
|
|
|
label1 = tk.Label(canvas, text="函数名:")
|
|
|
label1.place(x=650, y=50)
|
|
|
entry1 = tk.Entry(canvas)
|
|
|
entry1.place(x=650, y=100, width=300, height=40)
|
|
|
label2 = tk.Label(canvas, text="函数式:")
|
|
|
label2.place(x=650, y=150)
|
|
|
entry2 = tk.Entry(canvas)
|
|
|
entry2.place(x=650, y=200, width=300, height=40)
|
|
|
label3 = tk.Label(canvas, text="测试函数式:")
|
|
|
label3.place(x=650, y=250)
|
|
|
entry3 = tk.Entry(canvas)
|
|
|
entry3.place(x=650, y=300, width=300, height=40)
|
|
|
button1 = tk.Button(canvas, text="生成函数", command=add_func)
|
|
|
button1.place(x=650, y=400)
|
|
|
button2 = tk.Button(canvas, text="函数曲线", command=customized_curve)
|
|
|
button2.place(x=750, y=400)
|
|
|
button3 = tk.Button(canvas, text="函数确认", command=func_save)
|
|
|
button3.place(x=850, y=400)
|
|
|
# subwindow.mainloop()
|
|
|
|
|
|
|
|
|
def main():
|
|
|
global Q_root, F_root,root_window
|
|
|
jis()
|
|
|
# gl_data.LOW, gl_data.HIGH = int(gl_data.LOW*screen_size), int(gl_data.HIGH*screen_size)
|
|
|
gl_data.X = []
|
|
|
gl_data.X = []
|
|
|
window()
|
|
|
# 函数选择相关界面
|
|
|
F_root = tk.Canvas(root_window, width=int(310*screen_size), height=int(290*screen_size))
|
|
|
F_root.place(x=int(560*screen_size), y=int(60*screen_size))
|
|
|
|
|
|
# 象限选择相关界面
|
|
|
Q_root = tk.Canvas(root_window, width=int(400*screen_size), height=int(50*screen_size))
|
|
|
Q_root.place(x=int(20*screen_size), y=int(410*screen_size))
|
|
|
|
|
|
buttons()
|
|
|
f_button()
|
|
|
q_button()
|
|
|
show_fit()
|
|
|
tk.Button(root_window, image=list_image[11], command=show_subwindow, relief=tk.FLAT, highlightthickness=0).place(x=int(640*screen_size), y=int(350)*screen_size)
|
|
|
# 设置Grid布局的列和行权重
|
|
|
root_window.protocol("WM_DELETE_WINDOW", close_window)
|
|
|
root_window.mainloop()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
main()
|
|
|
pass
|