diff --git a/.gitkeep b/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..359bb53
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..8d3a16c
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+FunctionDisplay_X5.py
\ No newline at end of file
diff --git a/.idea/ijf6mgr5.iml b/.idea/ijf6mgr5.iml
new file mode 100644
index 0000000..8388dbc
--- /dev/null
+++ b/.idea/ijf6mgr5.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..1ccab34
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..46632bb
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/20240307计算思维程序实践-第3章 数值计算与曲线绘制 .docx b/20240307计算思维程序实践-第3章 数值计算与曲线绘制 .docx
new file mode 100644
index 0000000..ca20ca4
Binary files /dev/null and b/20240307计算思维程序实践-第3章 数值计算与曲线绘制 .docx differ
diff --git a/image/下部背景.png b/image/下部背景.png
new file mode 100644
index 0000000..f610758
Binary files /dev/null and b/image/下部背景.png differ
diff --git a/image/下部背景@2x.png b/image/下部背景@2x.png
new file mode 100644
index 0000000..4117a49
Binary files /dev/null and b/image/下部背景@2x.png differ
diff --git a/image/下部背景@3x.png b/image/下部背景@3x.png
new file mode 100644
index 0000000..ec4b13e
Binary files /dev/null and b/image/下部背景@3x.png differ
diff --git a/image/勾选.png b/image/勾选.png
new file mode 100644
index 0000000..1f79713
Binary files /dev/null and b/image/勾选.png differ
diff --git a/image/勾选@2x.png b/image/勾选@2x.png
new file mode 100644
index 0000000..218acdd
Binary files /dev/null and b/image/勾选@2x.png differ
diff --git a/image/勾选@3x.png b/image/勾选@3x.png
new file mode 100644
index 0000000..7188964
Binary files /dev/null and b/image/勾选@3x.png differ
diff --git a/image/勾选选中.png b/image/勾选选中.png
new file mode 100644
index 0000000..7924490
Binary files /dev/null and b/image/勾选选中.png differ
diff --git a/image/勾选选中@2x.png b/image/勾选选中@2x.png
new file mode 100644
index 0000000..43afa0c
Binary files /dev/null and b/image/勾选选中@2x.png differ
diff --git a/image/勾选选中@3x.png b/image/勾选选中@3x.png
new file mode 100644
index 0000000..7851730
Binary files /dev/null and b/image/勾选选中@3x.png differ
diff --git a/image/右侧背景.png b/image/右侧背景.png
new file mode 100644
index 0000000..98e4b89
Binary files /dev/null and b/image/右侧背景.png differ
diff --git a/image/右侧背景@2x.png b/image/右侧背景@2x.png
new file mode 100644
index 0000000..d508637
Binary files /dev/null and b/image/右侧背景@2x.png differ
diff --git a/image/右侧背景@3x.png b/image/右侧背景@3x.png
new file mode 100644
index 0000000..7de0099
Binary files /dev/null and b/image/右侧背景@3x.png differ
diff --git a/image/导航背景.jpg b/image/导航背景.jpg
new file mode 100644
index 0000000..275a004
Binary files /dev/null and b/image/导航背景.jpg differ
diff --git a/image/导航背景@2x.png b/image/导航背景@2x.png
new file mode 100644
index 0000000..5122889
Binary files /dev/null and b/image/导航背景@2x.png differ
diff --git a/image/导航背景@3x.png b/image/导航背景@3x.png
new file mode 100644
index 0000000..981a4b6
Binary files /dev/null and b/image/导航背景@3x.png differ
diff --git a/image/文字背景.png b/image/文字背景.png
new file mode 100644
index 0000000..83d3134
Binary files /dev/null and b/image/文字背景.png differ
diff --git a/image/文字背景2.png b/image/文字背景2.png
new file mode 100644
index 0000000..a114b1d
Binary files /dev/null and b/image/文字背景2.png differ
diff --git a/image/文字背景2@2x.png b/image/文字背景2@2x.png
new file mode 100644
index 0000000..c7126bd
Binary files /dev/null and b/image/文字背景2@2x.png differ
diff --git a/image/文字背景2@3x.png b/image/文字背景2@3x.png
new file mode 100644
index 0000000..267e8ef
Binary files /dev/null and b/image/文字背景2@3x.png differ
diff --git a/image/文字背景@2x.png b/image/文字背景@2x.png
new file mode 100644
index 0000000..9f976a6
Binary files /dev/null and b/image/文字背景@2x.png differ
diff --git a/image/文字背景@3x.png b/image/文字背景@3x.png
new file mode 100644
index 0000000..0c911a8
Binary files /dev/null and b/image/文字背景@3x.png differ
diff --git a/image/用户命名并新增基本函数-点击.png b/image/用户命名并新增基本函数-点击.png
new file mode 100644
index 0000000..5c4b86b
Binary files /dev/null and b/image/用户命名并新增基本函数-点击.png differ
diff --git a/image/用户命名并新增基本函数-点击@2x.png b/image/用户命名并新增基本函数-点击@2x.png
new file mode 100644
index 0000000..56a9e14
Binary files /dev/null and b/image/用户命名并新增基本函数-点击@2x.png differ
diff --git a/image/用户命名并新增基本函数-点击@3x.png b/image/用户命名并新增基本函数-点击@3x.png
new file mode 100644
index 0000000..bb3cfa1
Binary files /dev/null and b/image/用户命名并新增基本函数-点击@3x.png differ
diff --git a/image/用户命名并新增基本函数.png b/image/用户命名并新增基本函数.png
new file mode 100644
index 0000000..1e0f408
Binary files /dev/null and b/image/用户命名并新增基本函数.png differ
diff --git a/image/用户命名并新增基本函数@2x.png b/image/用户命名并新增基本函数@2x.png
new file mode 100644
index 0000000..453249f
Binary files /dev/null and b/image/用户命名并新增基本函数@2x.png differ
diff --git a/image/用户命名并新增基本函数@3x.png b/image/用户命名并新增基本函数@3x.png
new file mode 100644
index 0000000..1546a58
Binary files /dev/null and b/image/用户命名并新增基本函数@3x.png differ
diff --git a/image/背景.jpg b/image/背景.jpg
new file mode 100644
index 0000000..6f0af51
Binary files /dev/null and b/image/背景.jpg differ
diff --git a/image/背景@2x.jpg b/image/背景@2x.jpg
new file mode 100644
index 0000000..365e47c
Binary files /dev/null and b/image/背景@2x.jpg differ
diff --git a/image/背景@3x.jpg b/image/背景@3x.jpg
new file mode 100644
index 0000000..356fb09
Binary files /dev/null and b/image/背景@3x.jpg differ
diff --git a/image/象限选择背景.png b/image/象限选择背景.png
new file mode 100644
index 0000000..1ca972a
Binary files /dev/null and b/image/象限选择背景.png differ
diff --git a/image/象限选择背景@2x.png b/image/象限选择背景@2x.png
new file mode 100644
index 0000000..c8f5b25
Binary files /dev/null and b/image/象限选择背景@2x.png differ
diff --git a/image/象限选择背景@3x.png b/image/象限选择背景@3x.png
new file mode 100644
index 0000000..23c9601
Binary files /dev/null and b/image/象限选择背景@3x.png differ
diff --git a/image/输入条.png b/image/输入条.png
new file mode 100644
index 0000000..adf0782
Binary files /dev/null and b/image/输入条.png differ
diff --git a/image/输入条@2x.png b/image/输入条@2x.png
new file mode 100644
index 0000000..b2867de
Binary files /dev/null and b/image/输入条@2x.png differ
diff --git a/image/输入条@3x.png b/image/输入条@3x.png
new file mode 100644
index 0000000..abafd68
Binary files /dev/null and b/image/输入条@3x.png differ
diff --git a/image/输出-点击.png b/image/输出-点击.png
new file mode 100644
index 0000000..0d06be3
Binary files /dev/null and b/image/输出-点击.png differ
diff --git a/image/输出-点击@2x.png b/image/输出-点击@2x.png
new file mode 100644
index 0000000..26c0c5a
Binary files /dev/null and b/image/输出-点击@2x.png differ
diff --git a/image/输出-点击@3x.png b/image/输出-点击@3x.png
new file mode 100644
index 0000000..dc6f3ad
Binary files /dev/null and b/image/输出-点击@3x.png differ
diff --git a/image/输出.png b/image/输出.png
new file mode 100644
index 0000000..833da41
Binary files /dev/null and b/image/输出.png differ
diff --git a/image/输出@2x.png b/image/输出@2x.png
new file mode 100644
index 0000000..7f963ee
Binary files /dev/null and b/image/输出@2x.png differ
diff --git a/image/输出@3x.png b/image/输出@3x.png
new file mode 100644
index 0000000..43357e1
Binary files /dev/null and b/image/输出@3x.png differ
diff --git a/image/长条输入框.png b/image/长条输入框.png
new file mode 100644
index 0000000..13031d2
Binary files /dev/null and b/image/长条输入框.png differ
diff --git a/image/长条输入框@2x.png b/image/长条输入框@2x.png
new file mode 100644
index 0000000..e53671b
Binary files /dev/null and b/image/长条输入框@2x.png differ
diff --git a/image/长条输入框@3x.png b/image/长条输入框@3x.png
new file mode 100644
index 0000000..006b8b8
Binary files /dev/null and b/image/长条输入框@3x.png differ
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..ba63e6e
Binary files /dev/null and b/requirements.txt differ
diff --git a/step1/function.json b/step1/function.json
new file mode 100644
index 0000000..e5e645c
--- /dev/null
+++ b/step1/function.json
@@ -0,0 +1 @@
+{"sin(x)":"sin(x)","cos(x)":"cos(x)","tan(x)":"tan(x)"}
\ No newline at end of file
diff --git a/step1/step.py b/step1/step.py
new file mode 100644
index 0000000..51459ea
--- /dev/null
+++ b/step1/step.py
@@ -0,0 +1 @@
+############### 请在右侧图形化界面,全屏展示界面,完成本关卡 ###################
\ No newline at end of file
diff --git a/step1/step1.sh b/step1/step1.sh
new file mode 100644
index 0000000..94ae51e
--- /dev/null
+++ b/step1/step1.sh
@@ -0,0 +1,6 @@
+xrandr --addmode VNC-0 "1920x1080"
+xrandr --output VNC-0 --mode "1920x1080"
+nohup python3 x5/FunctionDisplay_X5.py &
+echo "编译成功"
+echo "运行成功"
+echo "测评成功"
\ No newline at end of file
diff --git a/x1/x1_1.py b/x1/x1_1.py
new file mode 100644
index 0000000..2519c93
--- /dev/null
+++ b/x1/x1_1.py
@@ -0,0 +1,11 @@
+import numpy as np
+
+def x1_1(): # 随机给出1000个点坐标,赋值给xyMap,
+ shape = [1000, 2]
+ xyMap = np.random.randint(-200, 200, size=shape)
+ return xyMap
+
+
+
+if __name__ == '__main__':
+ print(x1_1())
\ No newline at end of file
diff --git a/x1/x1_2.py b/x1/x1_2.py
new file mode 100644
index 0000000..771e7e8
--- /dev/null
+++ b/x1/x1_2.py
@@ -0,0 +1,27 @@
+import numpy as np
+def x1_2(problemIndex): # 程序给出任一函数 y=f(x)计算x=1到1000的y值,赋值给xyMap
+ # shape = [1000,2] #x值为1到1000,y为其对应函数值
+ xyMap = np.random.rand(1000, 2)
+ if problemIndex == 1:
+ for x in range(1, 1001):
+ xyMap[x - 1][0] = x # xyMap序号为0-999
+ xyMap[x - 1][1] = np.sin(x)
+ return xyMap
+ elif problemIndex == 2:
+ for x in range(1, 1001):
+ xyMap[x - 1][0] = x
+ xyMap[x - 1][1] = np.cos(x)
+ return xyMap
+ elif problemIndex == 3:
+ for x in range(1, 1001):
+ xyMap[x - 1][0] = x
+ xyMap[x - 1][1] = np.tan(x)
+ return xyMap
+ elif problemIndex == 4:
+ for x in range(1, 1001):
+ xyMap[x - 1][0] = x
+ xyMap[x - 1][1] = x * 2 + 2
+ return xyMap
+
+if __name__ == '__main__':
+ print(x1_2(4)[:50])
\ No newline at end of file
diff --git a/x1/x1_3.py b/x1/x1_3.py
new file mode 100644
index 0000000..f1222c9
--- /dev/null
+++ b/x1/x1_3.py
@@ -0,0 +1,43 @@
+import numpy as np
+import math
+
+def x1_3(problemIndex): # 程序给出任一函数y=f(x)计算x=-500到+500的y值赋值给xyMap
+ c = 0 # 此处x赋值为-500到-1到,1到500到1000个
+ shape = [1000, 2] # y赋值为其对应的函数
+ xyMap = np.random.rand(1000, 2)
+ if problemIndex == 1:
+ for x in range(-500, 500):
+ if (x == 0):
+ continue
+ xyMap[c][0] = x
+ xyMap[c][1] = math.sin(x)
+ c += 1
+ return xyMap
+ elif problemIndex == 2:
+ for x in range(-500, 500):
+ if (x == 0):
+ continue
+ xyMap[c][0] = x
+ xyMap[c][1] = math.cos(x)
+ c += 1
+ return xyMap
+ elif problemIndex == 3:
+ for x in range(-500, 500):
+ if (x == 0):
+ continue
+ xyMap[c][0] = x
+ xyMap[c][1] = math.tan(x)
+ c += 1
+ return xyMap
+ elif problemIndex == 4:
+ for x in range(-500, 501):
+ if (x == 0):
+ continue
+ xyMap[c][0] = x
+ xyMap[c][1] = x * 2 + 2
+ c += 1
+ return xyMap
+
+
+if __name__ == '__main__':
+ print(x1_3(1))
\ No newline at end of file
diff --git a/x1/x1_4.py b/x1/x1_4.py
new file mode 100644
index 0000000..14e46e6
--- /dev/null
+++ b/x1/x1_4.py
@@ -0,0 +1,31 @@
+import numpy as np
+import math
+
+def x1_4(ProblemIndex):
+ step = 3 # 步长
+ y = []
+ i, c = 0, 0
+ number = 1000 # 个数
+ while (True):
+ if (c == number):
+ break
+ else:
+ y.append(i)
+ i += step
+ c += 1
+ y = np.array(y)
+ xyMap = np.random.rand(1000, 2)
+ if (ProblemIndex == 1):
+ for i in range(len(y)):
+ xyMap[i][0] = y[i]
+ xyMap[i][1] = 2 * y[i] + 1
+ return xyMap
+ elif (ProblemIndex == 2):
+ for i in range(len(y)):
+ xyMap[i][0] = y[i]
+ xyMap[i][1] = y[i] / 3
+ return xyMap
+
+
+if __name__ == '__main__':
+ print(x1_4(1))
\ No newline at end of file
diff --git a/x3/FunctionDisplay_X3.py b/x3/FunctionDisplay_X3.py
new file mode 100644
index 0000000..d48c113
--- /dev/null
+++ b/x3/FunctionDisplay_X3.py
@@ -0,0 +1,362 @@
+import math
+from collections import OrderedDict
+from time import sleep
+from ttkbootstrap import *
+import tkinter.font as tkFont
+from tkinter import messagebox
+from tkinter.ttk import Treeview
+
+import sympy
+from numpy import arange
+from functionUtil import FunctionUtil
+
+
+# 获取文本的宽度和高度
+def get_text_dimensions(canvas, text, font):
+ text_id = canvas.create_text(0, 0, text=text, font=font, anchor="center")
+ bbox = canvas.bbox(text_id)
+ width = bbox[2] - bbox[0]
+ height = bbox[3] - bbox[1]
+ canvas.delete(text_id)
+ return width, height
+
+
+# 在画布中央绘制文本
+def center_text(canvas, text, font):
+ canvas_width = int(canvas.cget("width"))
+ text_width, text_height = get_text_dimensions(canvas, text, font)
+ x = canvas_width // 2
+ y = 200
+ canvas.create_text(x, y, text=text, font=font, anchor="center")
+
+
+class Graph(Canvas):
+ def __init__(self, master=None, **kwargs):
+ super().__init__(master, **kwargs)
+ self.width = int(self.cget('width'))
+ self.height = int(self.cget('height'))
+ self.origin = (self.width / 2, self.height / 2)
+ self.bili_x = 20
+ self.bili_y = 20
+ self.draw_axis()
+ self.draw_scale()
+
+ def draw_axis(self):
+ """
+ 绘制坐标轴
+ """
+ self.delete("all")
+ self.create_line(0, self.origin[1], self.width, self.origin[1], fill='black', arrow=LAST) # 一象限xy轴
+ self.create_line(self.origin[0], 0, self.origin[0], self.height, fill='black', arrow=FIRST)
+
+ def draw_scale(self):
+ """
+ 绘制刻度值
+ """
+ for i in range(-math.ceil((self.origin[0] / self.bili_x)) + 1, math.ceil((self.width - self.origin[0]) / self.bili_x)):
+ j = i * self.bili_x
+ if (i % 10 == 0):
+ self.create_line(j + self.origin[0], self.origin[1], j + self.origin[0], self.origin[1] - 5, fill='black')
+ self.create_text(j + self.origin[0], self.origin[1] + 10, text=i)
+ for i in range(-math.ceil((self.height - self.origin[1]) / self.bili_y) + 1, math.ceil((self.origin[1] / self.bili_y))):
+ j = -(i * self.bili_y)
+ if (i == 0):
+ continue
+ elif (i % 2 == 0):
+ self.create_line(self.origin[0], j + self.origin[1], self.origin[0] + 5, j + self.origin[1], fill='black')
+ self.create_text(self.origin[0] - 10, j + self.origin[1], text=i)
+
+ def switch_quadrant(self, quadrant):
+ """
+ 切换象限
+ """
+ if quadrant == 1:
+ self.origin = (50, self.height - 50)
+ else:
+ self.origin = (self.width / 2, self.height / 2)
+ self.draw_axis()
+ self.draw_scale()
+
+ def draw_graph(self, func, draw_precision=0.1, count=100, bili_x=20, bili_y=40, c='blue'):
+ 'xmin,xmax 自变量的取值范围; c 图像颜色'
+ 'x0,y0 原点坐标 w,h 横纵轴半长 draw_precision 步进'
+ self.bili_x, self.bili_y = int(bili_x), int(bili_y)
+ self.draw_axis()
+ self.draw_scale()
+ w1, w2 = self.bili_x, self.bili_y # w1,w2为自变量和函数值在横纵轴上的放大倍数
+ xmin, xmax = -math.ceil((self.origin[0] / self.bili_x)) + 1, math.ceil((self.width - self.origin[0]) / self.bili_x)
+ co2 = []
+ try:
+ for x in arange(xmin, xmax, draw_precision): # draw_precision----画图精度
+ y = sympy.sympify(func).subs("x", x).evalf()
+ coord = self.origin[0] + w1 * x, self.origin[1] - w2 * y, self.origin[0] + w1 * x + 1, self.origin[1] - w2 * y + 1
+ if abs(coord[1]) < self.height: # 超过w,h就截断
+ co2.append((self.origin[0] + w1 * x, self.origin[1] - w2 * y))
+ if count is None:
+ length = len(co2)
+ else:
+ length = len(co2[:int(count)])
+ for i in range(length):
+ if (draw_precision >= 1):
+ self.create_line(co2, fill=c, width=1)
+ if (i + 1 == len(co2)):
+ break
+ if (abs(co2[i][1] - co2[i + 1][1]) > 100):
+ continue
+ else:
+ self.create_line(co2[i], co2[i + 1], fill=c, width=1)
+ sleep(0.01)
+ self.update()
+ except Exception as E:
+ messagebox.showerror("错误", message=f"函数有误!\n{E}")
+
+
+class ExpressionCanvas(Canvas):
+ def __init__(self, master, *args, **kwargs):
+ super().__init__(master, *args, **kwargs)
+ self.node_width = 60
+ self.node_height = 30
+ self.x_spacing = 10
+ self.y_spacing = 70
+ self.level = {}
+
+ def add_node(self, text, x, y, parent=None):
+ node_width = len(text) * 5 + 20
+ if node_width < 40:
+ node_width = 50
+ # 创建节点
+ coords = [x - node_width / 2, y, x + node_width / 2, y + self.node_height]
+ if coords[1] in self.level:
+ max_x = max(self.level[coords[1]])
+ if coords[0] <= max_x:
+ x = max_x + node_width / 2 + self.x_spacing
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height,
+ fill="white")
+ sleep(0.2)
+ self.update()
+ elif text == "x":
+ x = self.coords(parent)[0] + node_width / 2
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height,
+ fill="white")
+ sleep(0.2)
+ self.update()
+ else:
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height, fill="white")
+ sleep(0.2)
+ self.update()
+ coords = [x - node_width / 2, y, x + node_width / 2, y + self.node_height]
+ if coords[1] in self.level:
+ self.level[coords[1]].append(coords[2])
+ else:
+ self.level[coords[1]] = [coords[2]]
+ text_id = self.create_text(x + 5, y + self.node_height // 2, text=text, anchor="center")
+ sleep(0.2)
+ self.update()
+ # 绘制父节点和当前节点的连线
+ if parent:
+ parent_coords = self.coords(parent)
+ parent_x = parent_coords[0] + (parent_coords[2] - parent_coords[0]) // 2
+ parent_y = parent_coords[1] + (parent_coords[3] - parent_coords[1]) // 2
+ self.create_line(parent_x, parent_y + self.node_height // 2, x, y, fill="black")
+ self.update()
+ return node_id
+
+ def draw_expression(self, expression, x, y, parent=None, sibling_width=0):
+ # 创建节点并绘制表达式文本
+ node = self.add_node(str(expression), x, y, parent=parent)
+ if expression.is_Atom:
+ return node
+ # 处理子表达式
+ num_children = len(expression.args)
+ total_width = num_children * self.node_width + (num_children - 1) * self.x_spacing
+ start_x = x - total_width // 2
+ for subexpr in expression.args:
+ subnode = self.draw_expression(subexpr, start_x, y + self.y_spacing, parent=node, sibling_width=total_width)
+ start_x += self.node_width + self.x_spacing
+ return node
+
+
+class FunctionDisplay(Frame):
+ def __init__(self, master, attr):
+ super().__init__(master)
+ self.attr = attr
+ self.font_style = tkFont.Font(family="Lucida Grande", size=30)
+ self.functions = FunctionUtil()
+ self.master = master
+ self.create_window()
+
+ def add_function(self):
+ """
+ 用户添加函数
+ """
+ input_func = self.func_input.get()
+ if input_func == "":
+ messagebox.showwarning("注意", message="请输入函数!")
+ return
+ elif input_func.find("=") < 0:
+ messagebox.showerror("注意", message="添加函数的格式为:\nSinPlusCos(x)=sin(x)+cos(x)")
+ return
+ left_var = input_func.split("=")[0]
+ right_var = input_func.split("=")[1]
+ try:
+ function = self.functions.get_function_by_iter(right_var)
+ sympy.sympify(function, evaluate=False)
+ except Exception as E:
+ messagebox.showerror("注意", message="函数解析错误,请仔细检查函数是否正确!")
+ self.func_input.delete(0, END)
+ return
+ if self.functions.check_function_exit(left_var):
+ result = messagebox.askokcancel(title='标题~', message=f'函数{left_var}已经存在,是否需要覆盖!')
+ if result:
+ self.functions.add_function(left_var, right_var)
+ messagebox.showinfo(title="提示", message="覆盖成功!")
+ self.func_input.delete(0, END)
+ return
+ self.functions.add_function(left_var, right_var)
+ messagebox.showinfo(title="提示", message="添加成功!")
+ self.func_input.delete(0, END)
+
+ def update_quadrant(self):
+ """
+ 更换象限
+ """
+ self.axis_canvas.switch_quadrant(self.quadrant.get())
+ self.print_function()
+
+ def print_function(self):
+ """
+ 输出
+ """
+ input_func = self.func_input.get()
+ if input_func == "":
+ messagebox.showwarning("注意", message="请输入函数!")
+ return
+ step = eval(self.x_step.get()) if not self.x_step.get() == "" else 0.1
+ count = self.x_count.get() if not self.x_count.get() == "" else None
+ x_scale = self.x_scale.get() if not self.x_scale.get() == "" else 20
+ y_scale = self.y_scale.get() if not self.y_scale.get() == "" else 40
+ if input_func.find("=") >= 0:
+ left_var = input_func.split("=")[0]
+ right_var = input_func.split("=")[1]
+ if self.functions.check_function_exit(right_var):
+ func = self.functions.get_function_by_iter(right_var)
+ self.axis_canvas.draw_graph(func, step, count,
+ x_scale, y_scale)
+ else:
+ self.axis_canvas.draw_graph(input_func, step, count,
+ x_scale, y_scale)
+ else:
+ if self.functions.check_function_exit(input_func):
+ func = self.functions.get_function_by_iter(input_func)
+ self.axis_canvas.draw_graph(func, step, count,
+ x_scale, y_scale)
+ else:
+ self.axis_canvas.draw_graph(input_func, step, count,
+ x_scale, y_scale)
+
+ def create_form(self):
+ bottom_frame = Frame(self.master, width=self.attr["width"], height=self.attr["height"] * 0.3)
+ self.func_input = Entry(bottom_frame, font=self.font_style, width=40)
+ self.func_input.grid(row=0, column=0, columnspan=4, padx=30)
+ self.add_func_button = Button(bottom_frame, text="用户命名并新增基本函数", command=self.add_function)
+ self.add_func_button.grid(row=0, column=4, padx=10)
+ Label(bottom_frame, text="x步长", font=("Lucida Grande", 20)).grid(row=1, column=0, padx=30)
+ self.x_step = Entry(bottom_frame, font=self.font_style, width=10)
+ self.x_step.grid(row=1, column=1, padx=10, pady=10)
+ Label(bottom_frame, text="x个数", font=("Lucida Grande", 20)).grid(row=1, column=2, padx=30)
+ self.x_count = Entry(bottom_frame, font=self.font_style, width=10)
+ self.x_count.grid(row=1, column=3, padx=10, pady=10)
+
+ Label(bottom_frame, text="坐标轴", font=("Lucida Grande", 20)).grid(row=2, column=0, padx=30)
+ self.quadrant = IntVar()
+ self.quadrant.set(4)
+ Radiobutton(bottom_frame, text="四象限", command=self.update_quadrant, value=4, variable=self.quadrant).grid(row=2, column=1, padx=10, pady=10)
+ Radiobutton(bottom_frame, text="一象限", command=self.update_quadrant, value=1, variable=self.quadrant).grid(row=2, column=2, padx=10, pady=10)
+
+ Label(bottom_frame, text="x放大倍数", font=("Lucida Grande", 20)).grid(row=3, column=0, padx=30)
+ self.x_scale = Entry(bottom_frame, font=self.font_style, width=10)
+ self.x_scale.grid(row=3, column=1, padx=10, pady=10)
+ Label(bottom_frame, text="y放大倍数", font=("Lucida Grande", 20)).grid(row=3, column=2, padx=30)
+ self.y_scale = Entry(bottom_frame, font=self.font_style, width=10)
+ self.y_scale.grid(row=3, column=3, padx=10, pady=10)
+
+ Button(bottom_frame, text="输出",
+ command=self.print_function, width=5).grid(row=1, rowspan=3, column=4, sticky="w")
+ bottom_frame.place(x=0, y=self.attr["height"] * 0.65 + 20)
+
+ def show_user_function(self):
+ children_window = Toplevel(root)
+ children_window.title("用户自定义函数")
+ children_window.geometry('350x260+450+200')
+ packet_frame = Frame(children_window)
+ packet_frame.grid(row=0, column=0, columnspan=3, padx=10, pady=5)
+ function_treeview = Treeview(packet_frame, columns=("function_name", "function"), show="headings")
+ function_treeview.heading("function_name", text="函数名称")
+ function_treeview.column("function_name", width=100, anchor=CENTER)
+ function_treeview.heading("function", text="函数体")
+ function_treeview.column("function", width=200, anchor=CENTER)
+ function_treeview.pack(side="left", fill="both")
+ scrollbar = Scrollbar(packet_frame, orient="vertical", command=function_treeview.yview)
+ scrollbar.pack(side="right", fill="y")
+ function_treeview.configure(yscrollcommand=scrollbar.set)
+
+ def delete_item():
+ selected_item = function_treeview.selection()
+ for item in selected_item:
+ item_data = function_treeview.item(item)
+ function_treeview.delete(item)
+ self.functions.data.pop(item_data["values"][0])
+ self.functions.save()
+
+ context_menu = Menu(root, tearoff=False)
+ context_menu.add_command(label="删除", command=delete_item)
+
+ def popup_menu(event):
+ if function_treeview.identify_region(event.x, event.y) == "cell":
+ function_treeview.selection_set(function_treeview.identify_row(event.y))
+ context_menu.post(event.x_root, event.y_root)
+
+ function_treeview.bind("", popup_menu)
+ for function_name, function in self.functions.data.items():
+ function_treeview.insert("", "end", values=(function_name, function))
+
+
+ def create_window(self):
+ self.axis_canvas = Graph(self.master, width=self.attr["width"] * 0.65, height=self.attr["height"] * 0.65, bg="#cdcdcd")
+ self.axis_canvas.place(x=0, y=0)
+ self.text_canvas = ExpressionCanvas(self.master, width=self.attr["width"] * 0.35, height=self.attr["height"] * 0.65, bg="#cdcdcd")
+ self.text_canvas.create_text(20 + 180, 35, text='可识别基本函数', fill='red', font=("Purisa", 25, "bold"))
+ menubar = Menu(root)
+ menubar.add_command(label='查看自定义函数', command=self.show_user_function)
+ root.config(menu=menubar)
+ text = "可支持下列函数的加减乘除组合运算\n" \
+ "\ty=sin(x)\n" \
+ "\tcos(x)\n" \
+ "\ttan(x)\n" \
+ "\tcot(x)\n" \
+ "\tx^n\n" \
+ "\tP1(x)=x^3+x^2+x+5\n" \
+ "---将括号内的表达式命名为P1,P1可\n" \
+ "出现于用户构造中"
+ self.text_canvas.create_text(20 + 180, 35, text='可识别基本函数', fill='red', font=("Purisa", 25, "bold"))
+ center_text(self.text_canvas, text, ("Lucida Grande", 17))
+ self.text_canvas.place(x=int(self.attr["width"] * 0.65), y=0)
+ self.create_form()
+
+
+if __name__ == '__main__':
+ root = Window()
+ screenwidth = root.winfo_screenwidth()
+ screenheight = root.winfo_screenheight()
+ root_attr = {
+ "width": 1200,
+ "height": 800,
+ }
+ 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 = FunctionDisplay(root, root_attr)
+ ttk.Style().configure("TButton", font="-size 18")
+ ttk.Style().configure("TRadiobutton", font="-size 18")
+ root.mainloop()
diff --git a/x3/function.json b/x3/function.json
new file mode 100644
index 0000000..8c369d5
--- /dev/null
+++ b/x3/function.json
@@ -0,0 +1 @@
+{"f1": "x**2 + 2*x + 1", "f3": "x**2", "f2": "(x/100)**2+2*(x/100)+1", "sinpluscos(x)": "cos(x) + sin(x)"}
\ No newline at end of file
diff --git a/x3/functionUtil.py b/x3/functionUtil.py
new file mode 100644
index 0000000..09e52e3
--- /dev/null
+++ b/x3/functionUtil.py
@@ -0,0 +1,57 @@
+import json
+import re
+
+
+class FunctionUtil:
+ def __init__(self):
+ self.filename = "./function.json"
+ self.data = {}
+ self.load()
+
+ def load(self):
+ """
+ 加载文件数据
+ """
+ try:
+ with open(self.filename, 'r', encoding="utf-8") as f:
+ self.data = json.load(f)
+ except FileNotFoundError:
+ pass
+
+ def save(self):
+ """
+ 将函数保存至json文件当中
+ """
+ with open(self.filename, "w", encoding="utf-8") as f:
+ json.dump(self.data, f)
+
+ def check_function_exit(self, function):
+ """
+ 检查用户输入的函数是否包含用户自定义函数
+ """
+ for key in self.data.keys():
+ if function.find(key) >=0:
+ return True
+ return False
+
+ def add_function(self, key, value):
+ """
+ 添加函数
+ """
+ self.data[key.strip()] = value.strip()
+ self.save()
+
+ def get_function_by_iter(self, key):
+ result = key
+ for dict_key in self.data.keys():
+ if result.find(dict_key) >= 0:
+ value = result.replace(dict_key, self.data[dict_key])
+ result = self.replace_values_recursive(value)
+ return result
+
+ def replace_values_recursive(self, value):
+ for key in self.data:
+ if key in value:
+ replacement = self.data[key]
+ value = value.replace(key, replacement)
+ return value
diff --git a/x3/test.py b/x3/test.py
new file mode 100644
index 0000000..b81dcd4
--- /dev/null
+++ b/x3/test.py
@@ -0,0 +1,9 @@
+import sympy
+
+from functionUtil import FunctionUtil
+
+
+# f = FunctionUtil()
+# print(f.get_function_by_iter("f1 + f3"))
+
+print(sympy.sympify("(x/100)**2+2*(x/100)+1"))
\ No newline at end of file
diff --git a/x3/x3_210.py b/x3/x3_210.py
new file mode 100644
index 0000000..a45d68b
--- /dev/null
+++ b/x3/x3_210.py
@@ -0,0 +1,25 @@
+def trapezoidal_rule(a, b, n):
+ """
+ 梯形法进行数值积分
+
+ 参数:
+ - f: 要积分的函数
+ - a: 积分区间的起始点
+ - b: 积分区间的结束点
+ - n: 划分的子区间数
+
+ 返回:
+ - 积分近似值
+ """
+ h = (b - a) / n # 子区间宽度
+ x = [a + i * h for i in range(n+1)] # 子区间的节点
+ y = [x_i ** 2 for x_i in x] # 子区间节点对应的函数值
+ integral = (h / 2) * (y[0] + 2 * sum(y[1:n]) + y[n]) # 梯形法计算积分值
+ return integral
+
+if __name__ == '__main__':
+ a = 0 # 积分区间的起始点
+ b = 1 # 积分区间的结束点
+ n = 100 # 划分的子区间数
+ integral = trapezoidal_rule(a, b, n)
+ print("数值积分的近似值:", integral)
\ No newline at end of file
diff --git a/x3/x3_211.py b/x3/x3_211.py
new file mode 100644
index 0000000..4ad9a00
--- /dev/null
+++ b/x3/x3_211.py
@@ -0,0 +1,25 @@
+def central_difference(f, x, h):
+ """
+ 中心差分法进行数值微分(计算导数)
+
+ 参数:
+ - f: 要求导数的函数
+ - x: 求导点的横坐标
+ - h: 步长
+
+ 返回:
+ - 导数的近似值
+ """
+ df = (f(x + h) - f(x - h)) / (2 * h) # 中心差分法计算导数
+
+ return df
+
+def f(x):
+ return x**2
+
+if __name__ == '__main__':
+ x = 2 # 求导点的横坐标
+ h = 0.01 # 步长
+
+ df = central_difference(f, x, h)
+ print("导数的近似值:", df)
\ No newline at end of file
diff --git a/x3/x3_212.py b/x3/x3_212.py
new file mode 100644
index 0000000..0ec7378
--- /dev/null
+++ b/x3/x3_212.py
@@ -0,0 +1,39 @@
+def newton_method(f, f_prime, x0, tol=1e-6, max_iter=100):
+ """
+ 牛顿迭代法计算函数值为0的解
+
+ 参数:
+ - f: 要求解的函数
+ - f_prime: 函数的导数
+ - x0: 初始猜测值
+ - tol: 容差(迭代停止的条件,可选,默认为1e-6)
+ - max_iter: 最大迭代次数(可选,默认为100)
+
+ 返回:
+ - 解的近似值
+ """
+ x = x0 # 初始猜测值
+ for _ in range(max_iter):
+ fx = f(x) # 函数值
+ if abs(fx) < tol:
+ # 已达到容差要求,返回解的近似值
+ return x
+ fpx = f_prime(x) # 函数的导数值
+ if abs(fpx) < tol:
+ # 导数值过小,无法继续迭代
+ break
+ x -= fx / fpx # 牛顿迭代公式
+ # 迭代未收敛或超过最大迭代次数,返回None表示未找到解
+ return None
+
+def f(x):
+ return x**2 - 4
+
+def f_prime(x):
+ return 2 * x
+
+
+if __name__ == '__main__':
+ x0 = 1 # 初始猜测值
+ solution = newton_method(f, f_prime, x0)
+ print("解的近似值:", solution)
\ No newline at end of file
diff --git a/x4/FunctionDisplay_X4.py b/x4/FunctionDisplay_X4.py
new file mode 100644
index 0000000..5ba9baf
--- /dev/null
+++ b/x4/FunctionDisplay_X4.py
@@ -0,0 +1,400 @@
+import math
+from collections import OrderedDict
+from time import sleep
+from ttkbootstrap import *
+import tkinter.font as tkFont
+from tkinter import messagebox
+from tkinter.ttk import Treeview
+
+import sympy
+from numpy import arange
+from functionUtil import FunctionUtil
+
+
+# 获取文本的宽度和高度
+def get_text_dimensions(canvas, text, font):
+ text_id = canvas.create_text(0, 0, text=text, font=font, anchor="center")
+ bbox = canvas.bbox(text_id)
+ width = bbox[2] - bbox[0]
+ height = bbox[3] - bbox[1]
+ canvas.delete(text_id)
+ return width, height
+
+
+# 在画布中央绘制文本
+def center_text(canvas, text, font):
+ canvas_width = int(canvas.cget("width"))
+ text_width, text_height = get_text_dimensions(canvas, text, font)
+ x = canvas_width // 2
+ y = 200
+ canvas.create_text(x, y, text=text, font=font, anchor="center")
+
+
+class Graph(Canvas):
+ def __init__(self, master=None, **kwargs):
+ super().__init__(master, **kwargs)
+ self.width = int(self.cget('width'))
+ self.height = int(self.cget('height'))
+ self.origin = (self.width / 2, self.height / 2)
+ self.bili_x = 20
+ self.bili_y = 20
+ self.draw_axis()
+ self.draw_scale()
+
+ def draw_axis(self):
+ """
+ 绘制坐标轴
+ """
+ self.delete("all")
+ self.create_line(0, self.origin[1], self.width, self.origin[1], fill='black', arrow=LAST) # 一象限xy轴
+ self.create_line(self.origin[0], 0, self.origin[0], self.height, fill='black', arrow=FIRST)
+
+ def draw_scale(self):
+ """
+ 绘制刻度值
+ """
+ for i in range(-math.ceil((self.origin[0] / self.bili_x)) + 1, math.ceil((self.width - self.origin[0]) / self.bili_x)):#将画布x轴每20个像素点作为一个刻度,i向上取整代表刻度值
+ j = i * self.bili_x #j代表的是i刻度值这一点的像素值
+ if (i % 10 == 0):#如果刻度值是十的倍数
+ self.create_line(j + self.origin[0], self.origin[1], j + self.origin[0], self.origin[1] - 5, fill='black')
+ self.create_text(j + self.origin[0], self.origin[1] + 10, text=i)
+ for i in range(-math.ceil((self.height - self.origin[1]) / self.bili_y) + 1, math.ceil((self.origin[1] / self.bili_y))):#将画布y轴每20个像素点作为一个刻度,i向上取整代表刻度值
+ j = -(i * self.bili_y)
+ if (i == 0):#不重复写零点
+ continue
+ elif (i % 2 == 0):
+ self.create_line(self.origin[0], j + self.origin[1], self.origin[0] + 5, j + self.origin[1], fill='black')
+ self.create_text(self.origin[0] - 10, j + self.origin[1], text=i)
+
+ def switch_quadrant(self, quadrant):
+ """
+ 切换象限
+ """
+ if quadrant == 1:
+ self.origin = (50, self.height - 50)
+ else:
+ self.origin = (self.width / 2, self.height / 2)
+ self.draw_axis()
+ self.draw_scale()
+
+ def get_xy(self):
+ return -math.ceil((self.origin[0] / self.bili_x)) + 1, math.ceil((self.width - self.origin[0]) / self.bili_x)
+
+ def draw_graph(self, func, draw_precision=0.1, count=1000, bili_x=20, bili_y=40, c='blue'):
+ 'xmin,xmax 自变量的取值范围; c 图像颜色'
+ 'x0,y0 原点坐标 w,h 横纵轴半长 draw_precision 步进'
+ self.bili_x, self.bili_y = int(bili_x), int(bili_y)
+ self.draw_axis()
+ self.draw_scale()
+ w1, w2 = self.bili_x, self.bili_y # w1,w2为自变量和函数值在横纵轴上的放大倍数
+ xmin, xmax = self.get_xy()
+ co2 = []
+ try:
+ for x in arange(xmin, xmax, draw_precision): # draw_precision----画图精度
+ y = sympy.sympify(func, convert_xor=True).subs("x", x).evalf()
+ coord = self.origin[0] + w1 * x, self.origin[1] - w2 * y, self.origin[0] + w1 * x + 1, self.origin[1] - w2 * y + 1
+ if abs(coord[1]) < self.height: # 超过w,h就截断
+ co2.append((self.origin[0] + w1 * x, self.origin[1] - w2 * y))
+ if count is None:
+ length = len(co2)
+ else:
+ length = len(co2[:int(count)])
+ for i in range(length):
+ if (draw_precision >= 1):
+ self.create_line(co2, fill=c, width=1)
+ if (i + 1 == len(co2)):
+ break
+ if (abs(co2[i][1] - co2[i + 1][1]) > 100):
+ continue
+ else:
+ self.create_line(co2[i], co2[i + 1], fill=c, width=1)
+ sleep(0.01)
+ self.update()
+ except Exception as E:
+ messagebox.showerror("错误", message=f"函数有误!\n{E}")
+
+
+class ExpressionCanvas(Canvas):
+ def __init__(self, master, *args, **kwargs):
+ super().__init__(master, *args, **kwargs)
+ self.node_width = 60
+ self.node_height = 30
+ self.x_spacing = 10
+ self.y_spacing = 70
+ self.level = {}
+
+ def add_node(self, text, x, y, parent=None):
+ node_width = len(text) * 5 + 20
+ if node_width < 40:
+ node_width = 50
+ # 创建节点
+ coords = [x - node_width / 2, y, x + node_width / 2, y + self.node_height]
+ if coords[1] in self.level:
+ max_x = max(self.level[coords[1]])
+ if coords[0] <= max_x:
+ x = max_x + node_width / 2 + self.x_spacing
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height,
+ fill="white")
+ sleep(0.2)
+ self.update()
+ elif text == "x":
+ x = self.coords(parent)[0] + node_width / 2
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height,
+ fill="white")
+ sleep(0.2)
+ self.update()
+ else:
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height, fill="white")
+ sleep(0.2)
+ self.update()
+ coords = [x - node_width / 2, y, x + node_width / 2, y + self.node_height]
+ if coords[1] in self.level:
+ self.level[coords[1]].append(coords[2])
+ else:
+ self.level[coords[1]] = [coords[2]]
+ text_id = self.create_text(x + 5, y + self.node_height // 2, text=text, anchor="center")
+ sleep(0.2)
+ self.update()
+ # 绘制父节点和当前节点的连线
+ if parent:
+ parent_coords = self.coords(parent)
+ parent_x = parent_coords[0] + (parent_coords[2] - parent_coords[0]) // 2
+ parent_y = parent_coords[1] + (parent_coords[3] - parent_coords[1]) // 2
+ self.create_line(parent_x, parent_y + self.node_height // 2, x, y, fill="black")
+ self.update()
+ return node_id
+
+ def draw_expression(self, expression, x, y, parent=None, sibling_width=0):
+ # 创建节点并绘制表达式文本
+ node = self.add_node(str(expression), x, y, parent=parent)
+ if expression.is_Atom:
+ return node
+ # 处理子表达式
+ num_children = len(expression.args)
+ total_width = num_children * self.node_width + (num_children - 1) * self.x_spacing
+ start_x = x - total_width // 2
+ for subexpr in expression.args:
+ subnode = self.draw_expression(subexpr, start_x, y + self.y_spacing, parent=node, sibling_width=total_width)
+ start_x += self.node_width + self.x_spacing
+ return node
+
+
+class FunctionDisplay(Frame):
+ def __init__(self, master, attr):
+ super().__init__(master)
+ self.attr = attr
+ self.font_style = tkFont.Font(family="Lucida Grande", size=30)
+ self.functions = FunctionUtil()
+ self.master = master
+ self.create_window()
+
+ def clear_text_canvas(self, event):
+ def clear_text():
+ self.text_canvas.delete("all")
+ self.text_canvas.create_text(20 + 180, 20, text='可识别基本函数', fill='red', font=("Purisa", 25, "bold"))
+ center_text(self.text_canvas, self.text, ("Lucida Grande", 15))
+ self.menu = Menu(self, tearoff=False)
+ self.menu.add_command(label="重置", command=clear_text)
+ self.menu.post(event.x_root, event.y_root)
+
+ def add_function(self):
+ """
+ 用户添加函数
+ """
+ input_func = self.func_input.get()
+ if input_func == "":
+ messagebox.showwarning("注意", message="请输入函数!")
+ return
+ elif input_func.find("=") < 0:
+ messagebox.showerror("注意", message="添加函数的格式为:\nSinPlusCos(x)=sin(x)+cos(x)")
+ return
+ left_var = input_func.split("=")[0]
+ right_var = input_func.split("=")[1]
+ try:
+ function = self.functions.get_function_by_iter(right_var)
+ sympy.sympify(function, evaluate=False)
+ except Exception as E:
+ messagebox.showerror("注意", message="函数解析错误,请仔细检查函数是否正确!")
+ self.func_input.delete(0, END)
+ return
+ if self.functions.check_function_exit(left_var):
+ result = messagebox.askokcancel(title='标题~', message=f'函数{left_var}已经存在,是否需要覆盖!')
+ if result:
+ self.functions.add_function(left_var, right_var)
+ messagebox.showinfo(title="提示", message="覆盖成功!")
+ self.func_input.delete(0, END)
+ return
+ self.functions.add_function(left_var, right_var)
+ messagebox.showinfo(title="提示", message="添加成功!")
+ self.func_input.delete(0, END)
+
+ def update_quadrant(self):
+ """
+ 更换象限
+ """
+ self.axis_canvas.switch_quadrant(self.quadrant.get())
+ self.print_function()
+
+ def print_function(self):
+ """
+ 输出
+ """
+ self.text_canvas.delete("all")
+ self.text_canvas.level.clear()
+ input_func = self.func_input.get()
+ if input_func == "":
+ messagebox.showwarning("注意", message="请输入函数!")
+ return
+ step = eval(self.x_step.get()) if not self.x_step.get() == "" else 0.1
+ count = self.x_count.get() if not self.x_count.get() == "" else None
+ x_scale = self.x_scale.get() if not self.x_scale.get() == "" else 20
+ y_scale = self.y_scale.get() if not self.y_scale.get() == "" else 40
+ if input_func.find("=") >= 0:
+ left_var = input_func.split("=")[0]
+ right_var = input_func.split("=")[1]
+ if self.functions.check_function_exit(right_var):
+ func = self.functions.get_function_by_iter(right_var)
+ self.axis_canvas.draw_graph(func, step, count,
+ x_scale, y_scale)
+ self.text_canvas.draw_expression(sympy.sympify(func, evaluate=False, convert_xor=True), int(self.text_canvas.cget("width")) // 2, self.text_canvas.y_spacing)
+ else:
+ self.axis_canvas.draw_graph(right_var, step, count,
+ x_scale, y_scale)
+ self.text_canvas.draw_expression(sympy.sympify(right_var, evaluate=False, convert_xor=True), int(self.text_canvas.cget("width")) // 2, self.text_canvas.y_spacing)
+ else:
+ if self.functions.check_function_exit(input_func):
+ func = self.functions.get_function_by_iter(input_func)
+ self.axis_canvas.draw_graph(func, step, count,
+ x_scale, y_scale)
+ self.text_canvas.draw_expression(sympy.sympify(func, evaluate=False, convert_xor=True), int(self.text_canvas.cget("width")) // 2, self.text_canvas.y_spacing)
+ else:
+ self.axis_canvas.draw_graph(input_func, step, count,
+ x_scale, y_scale)
+ self.text_canvas.draw_expression(sympy.sympify(input_func, evaluate=False, convert_xor=True), int(self.text_canvas.cget("width")) // 2, self.text_canvas.y_spacing)
+
+ def create_form(self):
+ bottom_frame = Frame(self.master, width=self.attr["width"], height=self.attr["height"] * 0.3)
+ self.func_input = Entry(bottom_frame, font=self.font_style, width=40)
+ self.func_input.grid(row=0, column=0, columnspan=4, padx=30)
+ self.add_func_button = Button(bottom_frame, text="用户命名并新增基本函数", command=self.add_function)
+ self.add_func_button.grid(row=0, column=4, padx=10)
+ Label(bottom_frame, text="x步长", font=("Lucida Grande", 20)).grid(row=1, column=0, padx=30)
+ self.x_step = Entry(bottom_frame, font=self.font_style, width=10)
+ self.x_step.grid(row=1, column=1, padx=10, pady=10)
+ Label(bottom_frame, text="x个数", font=("Lucida Grande", 20)).grid(row=1, column=2, padx=30)
+ self.x_count = Entry(bottom_frame, font=self.font_style, width=10)
+ self.x_count.grid(row=1, column=3, padx=10, pady=10)
+
+ Label(bottom_frame, text="坐标轴", font=("Lucida Grande", 20)).grid(row=2, column=0, padx=30)
+ self.quadrant = IntVar()
+ self.quadrant.set(4)
+ Radiobutton(bottom_frame, text="四象限", command=self.update_quadrant, value=4, variable=self.quadrant).grid(row=2, column=1, padx=10, pady=10)
+ Radiobutton(bottom_frame, text="一象限", command=self.update_quadrant, value=1, variable=self.quadrant).grid(row=2, column=2, padx=10, pady=10)
+
+ Label(bottom_frame, text="x放大倍数", font=("Lucida Grande", 20)).grid(row=3, column=0, padx=30)
+ self.x_scale = Entry(bottom_frame, font=self.font_style, width=10)
+ self.x_scale.grid(row=3, column=1, padx=10, pady=10)
+ Label(bottom_frame, text="y放大倍数", font=("Lucida Grande", 20)).grid(row=3, column=2, padx=30)
+ self.y_scale = Entry(bottom_frame, font=self.font_style, width=10)
+ self.y_scale.grid(row=3, column=3, padx=10, pady=10)
+
+ Button(bottom_frame, text="输出",
+ command=self.print_function, width=5).grid(row=1, rowspan=3, column=4, sticky="w")
+ bottom_frame.place(x=0, y=self.attr["height"] * 0.65 + 20)
+
+ def show_user_function(self):
+ children_window = Toplevel(root)
+ children_window.title("用户自定义函数")
+ children_window.geometry('350x260+450+200')
+ packet_frame = Frame(children_window)
+ packet_frame.grid(row=0, column=0, columnspan=3, padx=10, pady=5)
+ function_treeview = Treeview(packet_frame, columns=("function_name", "function"), show="headings")
+ function_treeview.heading("function_name", text="函数名称")
+ function_treeview.column("function_name", width=100, anchor=CENTER)
+ function_treeview.heading("function", text="函数体")
+ function_treeview.column("function", width=200, anchor=CENTER)
+ function_treeview.pack(side="left", fill="both")
+ scrollbar = Scrollbar(packet_frame, orient="vertical", command=function_treeview.yview)
+ scrollbar.pack(side="right", fill="y")
+ function_treeview.configure(yscrollcommand=scrollbar.set)
+
+ def delete_item():
+ selected_item = function_treeview.selection()
+ for item in selected_item:
+ item_data = function_treeview.item(item)
+ function_treeview.delete(item)
+ self.functions.data.pop(item_data["values"][0])
+ self.functions.save()
+
+ context_menu = Menu(root, tearoff=False)
+ context_menu.add_command(label="删除", command=delete_item)
+
+ def popup_menu(event):
+ if function_treeview.identify_region(event.x, event.y) == "cell":
+ function_treeview.selection_set(function_treeview.identify_row(event.y))
+ context_menu.post(event.x_root, event.y_root)
+
+ function_treeview.bind("", popup_menu)
+ for function_name, function in self.functions.data.items():
+ function_treeview.insert("", "end", values=(function_name, function))
+
+ def create_window(self):
+ self.axis_canvas = Graph(self.master, width=self.attr["width"] * 0.65, height=self.attr["height"] * 0.65, bg="#cdcdcd")
+ self.axis_canvas.place(x=0, y=0)
+ self.text_canvas = ExpressionCanvas(self.master, width=self.attr["width"] * 0.35, height=self.attr["height"] * 0.65, bg="#cdcdcd")
+ menubar = Menu(root)
+ menubar.add_command(label='查看自定义函数', command=self.show_user_function)
+ root.config(menu=menubar)
+ # self.text = "可支持下列函数的加减乘除组合运算\n" \
+ # "常用运算符:+,-,*,/,**,//,%\n" \
+ # "常用函数:\n" \
+ # " sqrt(x):求平方根\n" \
+ # "数学常数:\n" \
+ # " 虚数单位:I\n" \
+ # " 自然对数的底:E\n" \
+ # " 无穷大:oo\n" \
+ # " 圆周率:pi\n" \
+ # "三角函数:sin(x),cos(x),tan(x)\n" \
+ # " sec(x),csc(x),cot(x),sinc(x)\n" \
+ # " 及其反函数:sinh(),cosh()等\n" \
+ # "复杂函数:\n" \
+ # " 伽马函数:gamma(x)\n" \
+ # " 贝塔函数:beta()\n" \
+ # " 误差函数:erf(x)\n" \
+ # "指数运算:\n" \
+ # " 指数运算:exp()\n" \
+ # " 自然对数:log()\n" \
+ # " 以十为底的对数:log(var, 10)\n" \
+ # " 自然对数:ln()或log()\n"
+ self.text = "可支持下列函数的加减乘除组合运算\n" \
+ "\ty=sin(x)\n" \
+ "\tcos(x)\n" \
+ "\ttan(x)\n" \
+ "\tcot(x)\n" \
+ "\tx^n\n" \
+ "\tP1(x)=x^3+x^2+x+5\n" \
+ "---将括号内的表达式命名为P1,P1可\n" \
+ "出现于用户构造中"
+ self.text_canvas.create_text(20 + 180, 20, text='可识别基本函数', fill='red', font=("Purisa", 25, "bold"))
+ center_text(self.text_canvas, self.text, ("Lucida Grande", 15))
+ self.text_canvas.bind("", func=self.clear_text_canvas)
+ self.text_canvas.place(x=int(self.attr["width"] * 0.65), y=0)
+ self.create_form()
+
+
+if __name__ == '__main__':
+ root = Window()
+ screenwidth = root.winfo_screenwidth()
+ screenheight = root.winfo_screenheight()
+ root_attr = {
+ "width": 1200,
+ "height": 800,
+ }
+ 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 = FunctionDisplay(root, root_attr)
+ ttk.Style().configure("TButton", font="-size 18")
+ ttk.Style().configure("TRadiobutton", font="-size 18")
+ root.mainloop()
diff --git a/x4/function.json b/x4/function.json
new file mode 100644
index 0000000..a20339e
--- /dev/null
+++ b/x4/function.json
@@ -0,0 +1,8 @@
+{
+ "f1": "sin(x)+cos(x)+p3(x)",
+ "f3": "x**2",
+ "f2": "(x/100)**2+2*(x/100)+1",
+ "SinPlusCos(x)": "sin(x) + cos(x)",
+ "superFunc": "(x/100)**2 + 2*(x/100) + 1",
+ "func": "3 * x + sin(x) * cos(x)"
+}
\ No newline at end of file
diff --git a/x4/functionUtil.py b/x4/functionUtil.py
new file mode 100644
index 0000000..09e52e3
--- /dev/null
+++ b/x4/functionUtil.py
@@ -0,0 +1,57 @@
+import json
+import re
+
+
+class FunctionUtil:
+ def __init__(self):
+ self.filename = "./function.json"
+ self.data = {}
+ self.load()
+
+ def load(self):
+ """
+ 加载文件数据
+ """
+ try:
+ with open(self.filename, 'r', encoding="utf-8") as f:
+ self.data = json.load(f)
+ except FileNotFoundError:
+ pass
+
+ def save(self):
+ """
+ 将函数保存至json文件当中
+ """
+ with open(self.filename, "w", encoding="utf-8") as f:
+ json.dump(self.data, f)
+
+ def check_function_exit(self, function):
+ """
+ 检查用户输入的函数是否包含用户自定义函数
+ """
+ for key in self.data.keys():
+ if function.find(key) >=0:
+ return True
+ return False
+
+ def add_function(self, key, value):
+ """
+ 添加函数
+ """
+ self.data[key.strip()] = value.strip()
+ self.save()
+
+ def get_function_by_iter(self, key):
+ result = key
+ for dict_key in self.data.keys():
+ if result.find(dict_key) >= 0:
+ value = result.replace(dict_key, self.data[dict_key])
+ result = self.replace_values_recursive(value)
+ return result
+
+ def replace_values_recursive(self, value):
+ for key in self.data:
+ if key in value:
+ replacement = self.data[key]
+ value = value.replace(key, replacement)
+ return value
diff --git a/x4/test.py b/x4/test.py
new file mode 100644
index 0000000..b81dcd4
--- /dev/null
+++ b/x4/test.py
@@ -0,0 +1,9 @@
+import sympy
+
+from functionUtil import FunctionUtil
+
+
+# f = FunctionUtil()
+# print(f.get_function_by_iter("f1 + f3"))
+
+print(sympy.sympify("(x/100)**2+2*(x/100)+1"))
\ No newline at end of file
diff --git a/x5/FunctionDisplay_X5.py b/x5/FunctionDisplay_X5.py
new file mode 100644
index 0000000..44581bc
--- /dev/null
+++ b/x5/FunctionDisplay_X5.py
@@ -0,0 +1,447 @@
+# -*- coding: utf-8 -*-
+from time import sleep
+from tkinter import *
+import tkinter.font as tkFont
+from tkinter import messagebox
+
+import numpy as np
+from matplotlib.figure import Figure
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+
+import sympy
+from numpy import arange
+from sympy import symbols, lambdify
+from functionUtil import FunctionUtil
+import math
+from PIL import ImageTk, Image
+import sys
+
+# 在画布中央绘制文本
+def center_text(canvas, text, font):
+ canvas_width = int(canvas.cget("width"))
+ x = canvas_width // 2
+ y = 200
+ canvas.create_text(x, y, text=text, font=font, anchor="center")
+
+
+class Graph(Canvas):
+ """
+ 绘制函数图形
+ """
+
+ def __init__(self, master=None, **kwargs):
+ super().__init__(master, **kwargs)
+ self.width = int(self.cget('width'))
+ self.height = int(self.cget('height'))
+ self.origin = (self.width / 2, self.height / 2)
+ self.config(bg="white")
+ self.bili_x = 20
+ self.bili_y = 20
+ self.draw_axis()
+ self.draw_scale()
+ self.fig = FigureCanvasTkAgg()
+ self.y_scale = 1.0
+
+
+ def draw_axis(self):
+ """
+ 绘制坐标轴
+ """
+ self.delete("all")
+ self.create_line(0, self.origin[1], self.width, self.origin[1], fill='black', arrow=LAST) # 一象限xy轴
+ self.create_line(self.origin[0], 0, self.origin[0], self.height, fill='black', arrow=FIRST)
+
+ def draw_scale(self):
+ """
+ 绘制刻度值
+ """
+ for i in range(-math.ceil((self.origin[0] / self.bili_x)) + 1,
+ math.ceil((self.width - self.origin[0]) / self.bili_x)):
+ j = i * self.bili_x
+ if (i % 10 == 0):
+ self.create_line(j + self.origin[0], self.origin[1], j + self.origin[0], self.origin[1] - 5,
+ fill='black')
+ self.create_text(j + self.origin[0], self.origin[1] + 10, text=i)
+ for i in range(-math.ceil((self.height - self.origin[1]) / self.bili_y) + 1,
+ math.ceil((self.origin[1] / self.bili_y))):
+ j = -(i * self.bili_y)
+ if i == 0:
+ continue
+ elif i % 2 == 0:
+ self.create_line(self.origin[0], j + self.origin[1], self.origin[0] + 5, j + self.origin[1],
+ fill='black')
+ self.create_text(self.origin[0] - 10, j + self.origin[1], text=i)
+
+ def switch_quadrant(self, quadrant):
+ """
+ 切换象限
+ """
+ if quadrant == 1:
+ self.origin = (50, self.height - 50)
+ else:
+ self.origin = (self.width / 2, self.height / 2)
+ self.draw_axis()
+ self.draw_scale()
+
+
+ def draw_graph_3d(self, func, draw_precision=0.1, count=1000, bili_x=20, bili_y=40, ):
+ self.fig.get_tk_widget().destroy()
+ self.delete("all")
+ # 创建 sympy 符号
+ x, y = symbols('x y')
+ self.bili_x, self.bili_y = int(bili_x), int(bili_y)
+ # 将表达式转换为可计算的函数
+ expr = lambdify((x, y), func, modules=['numpy'])
+ xmin, xmax = -math.ceil((self.origin[0] / self.bili_x)) + 1, math.ceil(
+ (self.width - self.origin[0]) / self.bili_x)
+ # 创建数据网格
+ X = np.linspace(xmin, xmax, int(draw_precision * 100))
+ Y = np.linspace(xmin, xmax, int(draw_precision * 100))
+ X, Y = np.meshgrid(X, Y)
+ Z = expr(X, Y)
+ # 创建一个 Figure 对象
+ fig = Figure(figsize=(7, 5.5), dpi=120)
+ # 在 Figure 上创建一个 3D 子图
+ ax = fig.add_subplot(111, projection='3d')
+ ax.auto_scale_xyz(X, Y, Z)
+ # 绘制三维图形
+ ax.plot_surface(X, Y, Z, cmap='viridis')
+ self.fig = FigureCanvasTkAgg(fig, master=self)
+ self.fig.draw()
+ self.fig.get_tk_widget().pack(fill=BOTH, ipadx=0, ipady=0, pady=0, padx=0, expand=True)
+
+
+
+
+ def draw_graph_2d(self, func, draw_precision=0.1, count=1000, bili_x=20, bili_y=40, c='blue'):
+ 'xmin,xmax 自变量的取值范围; c 图像颜色'
+ 'x0,y0 原点坐标 w,h 横纵轴半长 draw_precision 步进'
+ self.fig.get_tk_widget().destroy()
+ self.bili_x, self.bili_y = int(bili_x), int(bili_y)
+ self.draw_axis()
+ self.draw_scale()
+ w1, w2 = self.bili_x, self.bili_y # w1,w2为自变量和函数值在横纵轴上的放大倍数
+ xmin, xmax = -math.ceil((self.origin[0] / self.bili_x)) + 1, math.ceil(
+ (self.width - self.origin[0]) / self.bili_x)
+ co2 = []
+ try:
+ for x in arange(xmin, xmax, draw_precision): # draw_precision----画图精度
+ y = sympy.sympify(func, convert_xor=True).subs("x", x).evalf()
+ coord = self.origin[0] + w1 * x, self.origin[1] - w2 * y, self.origin[0] + w1 * x + 1, self.origin[
+ 1] - w2 * y + 1
+ # if abs(coord[1]) < int(self.height): # 超过w,h就截断 #已经将截断注释
+ co2.append((self.origin[0] + w1 * x, self.origin[1] - w2 * y))
+ if count is None:
+ length = len(co2)
+ else:
+ length = len(co2[:int(count)])
+ for i in range(length):
+ if (draw_precision >= 1):
+ self.create_line(co2, fill=c, width=1)
+ if (i + 1 == len(co2)):
+ break
+ if (abs(co2[i][1] - co2[i + 1][1]) > 100):
+ continue
+ else:
+ self.create_line(co2[i], co2[i + 1], fill=c, width=1)
+ # sleep(0.01)
+ self.update()
+ except Exception as E:
+ messagebox.showerror("错误", message=f"函数有误,错误信息如下!\n{E}")
+
+
+ def draw_graph(self,dimension,func, draw_precision=0.1, count=1000, bili_x=20, bili_y=40, ):
+ if dimension==1:
+ self.draw_graph_3d(func, draw_precision, count, bili_x, bili_y,)
+ else:
+ self.draw_graph_2d(func, draw_precision, count, bili_x, bili_y,c='blue')
+
+class ExpressionCanvas(Canvas):
+ def __init__(self, master, *args, **kwargs):
+ super().__init__(master, *args, **kwargs)
+ self.node_width = 100
+ self.node_height = 40
+ self.x_spacing = 15
+ self.y_spacing = 70
+ self.level = {}
+
+ def add_node(self, text, x, y, parent=None):
+ node_width = len(text) * 15 + 20
+ if node_width < 40:
+ node_width = 50
+ # 创建节点
+ coords = [x - node_width / 2, y, x + node_width / 2, y + self.node_height]
+ if coords[1] in self.level:
+ max_x = max(self.level[coords[1]])
+ if coords[0] <= max_x:
+ x = max_x + node_width / 2 + self.x_spacing
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height,
+ fill="white")
+ sleep(0.2)
+ self.update()
+ elif text == "x":
+ x = self.coords(parent)[0] + node_width / 2
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height,
+ fill="white")
+ sleep(0.2)
+ self.update()
+ else:
+ node_id = self.create_rectangle(x - node_width / 2, y, x + node_width / 2, y + self.node_height,
+ fill="white")
+ sleep(0.2)
+ self.update()
+ coords = [x - node_width / 2, y, x + node_width / 2, y + self.node_height]
+ if coords[1] in self.level:
+ self.level[coords[1]].append(coords[2])
+ else:
+ self.level[coords[1]] = [coords[2]]
+ text_id = self.create_text(x + 5, y + self.node_height // 2, text=text, anchor="center", font=("", 15))
+ sleep(0.2)
+ self.update()
+ # 绘制父节点和当前节点的连线
+ if parent:
+ try:
+ parent_coords = self.coords(parent)
+ parent_x = parent_coords[0] + (parent_coords[2] - parent_coords[0]) // 2
+ parent_y = parent_coords[1] + (parent_coords[3] - parent_coords[1]) // 2
+ self.create_line(parent_x, parent_y + self.node_height // 2, x, y, fill="black")
+ self.update()
+ except Exception as E:
+ pass
+ return node_id
+
+ def draw_expression(self, expression, x, y, parent=None, sibling_width=0):
+ # 创建节点并绘制表达式文本
+ node = self.add_node(str(expression), x, y, parent=parent)
+ if expression.is_Atom:
+ return node
+ # 处理子表达式
+ num_children = len(expression.args)
+ total_width = num_children * self.node_width + (num_children - 1) * self.x_spacing
+ start_x = x - total_width // 2
+ for subexpr in expression.args:
+ subnode = self.draw_expression(subexpr, start_x, y + self.y_spacing, parent=node, sibling_width=total_width)
+ start_x += self.node_width + self.x_spacing
+ return node
+
+
+class FunctionDisplay(Canvas):
+ def __init__(self, master, *args, **kwargs):
+ super().__init__(master, *args, **kwargs)
+ self.font_style = tkFont.Font(family="Lucida Grande", size=30)
+ self.functions = FunctionUtil()
+ self.width = int(self.cget("width"))
+ self.height = int(self.cget("height"))
+ self.background_img = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/背景@3x.jpg").resize((self.width, self.height)))
+ self.create_image(0, 0, image=self.background_img, anchor=NW)
+ self.master = master
+ self.init_window()
+ self.load_user_function()
+
+ def add_function(self):
+ """
+ 用户添加函数
+ """
+ input_func = self.func_input.get()
+ if input_func == "":
+ messagebox.showwarning("注意", message="请输入函数!")
+ return
+ elif input_func.find("=") < 0:
+ messagebox.showerror("注意", message="添加函数的格式为:\nSinPlusCos(x)=sin(x)+cos(x)")
+ return
+ left_var = input_func.split("=")[0]
+ right_var = input_func.split("=")[1]
+ try:
+ function = self.functions.get_function_by_iter(right_var)
+ sympy.sympify(function, evaluate=False)
+ except Exception as E:
+ messagebox.showerror("注意", message="函数解析错误,请仔细检查函数是否正确!")
+ self.func_input.delete(0, END)
+ return
+ if self.functions.check_function_exit(left_var):
+ result = messagebox.askokcancel(title='提示', message=f'函数{left_var}已经存在,是否需要覆盖!')
+ if result:
+ self.functions.add_function(left_var, right_var)
+ messagebox.showinfo(title="提示", message="覆盖成功!")
+ self.func_input.delete(0, END)
+ self.load_user_function()
+ return
+ self.functions.add_function(left_var, right_var)
+ messagebox.showinfo(title="提示", message="添加成功!")
+ self.func_input.delete(0, END)
+ self.load_user_function()
+
+ def update_dimension(self):
+ """
+ 更换维度
+ """
+ dimension=self.dimension.get()
+ self.print_function()
+
+ def update_quadrant(self):
+ """
+ 更换象限
+ """
+ self.axis_canvas.switch_quadrant(self.quadrant.get())
+ self.print_function()
+
+ def print_function(self):
+ """
+ 输出
+ """
+ dimension=self.dimension.get()
+ self.text_canvas.delete("all")
+ self.text_canvas.level.clear()
+ input_func = self.func_input.get()
+ if input_func == "":
+ messagebox.showwarning("注意", message="请输入函数!")
+ return
+ step = eval(self.x_step.get()) if not self.x_step.get() == "" else 0.1
+ count = self.x_count.get() if not self.x_count.get() == "" else None
+ x_scale = int(self.x_scale.get())*20 if not self.x_scale.get() == "" else 20
+ y_scale = int(self.y_scale.get())*40 if not self.y_scale.get() == "" else 40
+ if input_func.find("=") >= 0:
+ input_func = input_func.split("=")[1]
+ if self.functions.check_function_exit(input_func):
+ func = self.functions.get_function_by_iter(input_func)
+ self.axis_canvas.draw_graph(dimension,func, step, count, x_scale, y_scale)
+ self.text_canvas.draw_expression(sympy.sympify(func, evaluate=False, convert_xor=True),
+ int(self.text_canvas.cget("width")) // 2, self.text_canvas.y_spacing)
+ else:
+ self.axis_canvas.draw_graph(dimension,input_func, step, count, x_scale, y_scale)
+ self.text_canvas.draw_expression(sympy.sympify(input_func, evaluate=False, convert_xor=True),
+ int(self.text_canvas.cget("width")) // 2, self.text_canvas.y_spacing)
+
+ def load_user_function(self):
+ self.user_function_canvas.delete(ALL)
+ self.user_function_canvas.create_text(20 + 90, 35, text='可识别基本函数', fill='red',
+ font=("Purisa", 20, "bold"))
+ num = 2
+ self.user_function_canvas.create_text(0, 70, anchor="nw", text="函数名", font=("", 15))
+ self.user_function_canvas.create_text(150, 70, anchor="nw", text="函数体", font=("", 15))
+ for function, function_body in self.functions.data.items():
+ self.user_function_canvas.create_text(0, 20 * num + 50, anchor="nw", text=function, font=("", 15))
+ self.user_function_canvas.create_text(150, 20 * num + 50, anchor="nw", text=function_body, font=("", 15))
+ num += 1
+ self.user_function_canvas.update()
+ self.user_function_canvas.configure(scrollregion=self.user_function_canvas.bbox("all"))
+
+ def create_form(self):
+ bottom_frame = Canvas(self, width=self.width, height=self.height * 0.3, highlightthickness=0)
+ self.back_image = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/下部背景@3x.png").resize((self.width, int(self.height * 0.3))))
+ bottom_frame.create_image(0, 0, image=self.back_image, anchor=NW)
+ label_width, entry_width, label_margin_left, margin_left, height, margin_top = 100, 215, 120 + 50, 120, 42, 20
+ self.func_input = Entry(bottom_frame, font=self.font_style)
+ self.func_input.place(x=margin_left, y=margin_top, anchor=NW, width=1000, height=height)
+ self.add_func_image = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/用户命名并新增基本函数@3x.png").resize((180, 62)))
+ self.add_func_button = Button(bottom_frame, image=self.add_func_image, bd=0, relief="solid", bg="#f7f7f7",
+ highlightthickness=0, command=self.add_function)
+ self.add_func_button.place(x=1140, y=10, anchor=NW)
+
+ self.label_img = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/文字背景@3x.png").resize((100, 42)))
+ bottom_frame.create_image(label_margin_left-100, 112, image=self.label_img)
+ bottom_frame.create_text(label_margin_left-100, 112, text="x步长", fill="white", font=("", 20))
+ self.x_step = Entry(bottom_frame, font=self.font_style)
+ self.x_step.place(x=margin_left + label_width-100, y=112 - 21, width=215, height=42)
+
+ self.label1_img = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/文字背景@3x.png").resize((100, 42)))
+ bottom_frame.create_image(label_margin_left-100, 171, image=self.label1_img)
+ bottom_frame.create_text(label_margin_left-100, 170, text="x个数", fill="white", font=("", 20))
+ self.x_count = Entry(bottom_frame, font=self.font_style)
+ self.x_count.place(x=margin_left + label_width-100, y=112 + 39, width=215, height=42)
+
+ self.big_label_img = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/文字背景2@3x.png").resize((label_width+5, height * 2 + margin_top)))
+ bottom_frame.create_image(label_margin_left + label_width + entry_width - 80, 112 + 31, image=self.big_label_img)
+ bottom_frame.create_text(label_margin_left + label_width + entry_width - 80, 112 + 31, text="坐标轴", fill="white", font=("", 25))
+ self.quadrant = IntVar()
+ self.quadrant.set(4)
+ Radiobutton(bottom_frame, text="四象限", command=self.update_quadrant, font=("", 17),
+ bg="#b9b9f7",highlightthickness=0, highlightcolor="#aaaaf2",
+ value=4, variable=self.quadrant).place(x=label_margin_left + label_width * 2 + entry_width -128, y=90,
+ height=(height * 2 + margin_top) / 2, width=entry_width, anchor=NW)
+ Radiobutton(bottom_frame, text="一象限", command=self.update_quadrant, font=("", 17), bg="#b9b9f7",
+ highlightthickness=0, highlightcolor="#aaaaf2",
+ value=1, variable=self.quadrant).place(x=label_margin_left + label_width * 2 + entry_width -128, y=90 + (height * 2 + margin_top) / 2,
+ height=(height * 2 + margin_top) / 2, width=entry_width, anchor=NW)
+
+
+ self.big_label_img1 = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/文字背景2@3x.png").resize((label_width+5, height * 2 + margin_top)))
+ bottom_frame.create_image(label_margin_left + label_width + entry_width+278, 112 + 31, image=self.big_label_img1)
+ bottom_frame.create_text(label_margin_left + label_width + entry_width+278, 112 + 31, text="维度", fill="white", font=("", 25))
+ self.dimension = IntVar()
+ self.dimension.set(4)
+ Radiobutton(bottom_frame, text="二维", command=self.update_dimension, font=("", 17),
+ bg="#b9b9f7",highlightthickness=0, highlightcolor="#aaaaf2",
+ value=4, variable=self.dimension).place(x=label_margin_left + label_width * 2 + entry_width+230, y=90,
+ height=(height * 2 + margin_top) / 2, width=entry_width, anchor=NW)
+ Radiobutton(bottom_frame, text="三维", command=self.update_dimension, font=("", 17), bg="#b9b9f7",
+ highlightthickness=0, highlightcolor="#aaaaf2",
+ value=1, variable=self.dimension).place(x=label_margin_left + label_width * 2 + entry_width+230, y=90 + (height * 2 + margin_top) / 2,
+ height=(height * 2 + margin_top) / 2, width=entry_width, anchor=NW)
+
+
+ self.x_scale = Entry(bottom_frame, font=self.font_style)
+ self.x_scale.place(x=margin_left + label_width+100, y=112 - 21, width=215, height=42)
+ label_x = label_margin_left + 840
+ label_y = 112
+ self.label_img1 = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/文字背景@3x.png").resize((130, 42)))
+ bottom_frame.create_image(label_x+100, label_y, image=self.label_img1)
+ bottom_frame.create_text(label_x+100, label_y, text="x放大倍数", fill="white", font=("", 20))
+ entry_x = margin_left + label_width + 855
+ entry_y = 112 - 21
+ self.x_scale.place(x=entry_x+100, y=entry_y, width=215, height=42)
+
+
+ self.y_scale = Entry(bottom_frame, font=self.font_style)
+ self.y_scale.place(x=margin_left + label_width+100, y=112 - 21, width=215, height=42)
+ label_x = label_margin_left + 840
+ label_y = 170
+ bottom_frame.create_image(label_x+100, label_y, image=self.label_img1)
+ bottom_frame.create_text(label_x+100, label_y, text="y放大倍数", fill="white", font=("", 20))
+ entry_x = margin_left + label_width + 855
+ entry_y = 170 - 21
+ self.y_scale.place(x=entry_x+100, y=entry_y, width=215, height=42)
+
+ self.print_function_image = ImageTk.PhotoImage(Image.open(sys.path[0]+"/./image/输出-点击@3x.png").resize((120, 60)))
+ self.print_function_button = Button(bottom_frame, image=self.print_function_image, bd=0, relief="solid", bg="#f7f7f7",
+ highlightthickness=0, command=self.print_function)
+ self.print_function_button.place(x=1350, y=10, anchor=NW)
+ # Button(bottom_frame, text="输出", command=self.print_function, width=5) \
+ # .place(x=1350, y=95, anchor=NW)
+ bottom_frame.place(x=0, y=self.height * 0.65 + 40, anchor=NW)
+
+ def init_window(self):
+ self.axis_canvas = Graph(self, width=self.width * 0.45, height=self.height * 0.65,highlightthickness=0)
+ self.axis_canvas.place(x=0, y=0, anchor=NW)
+ self.text_canvas = ExpressionCanvas(self, width=self.width * 0.35,
+ height=self.height * 0.65, bg="white",highlightthickness=0)
+ self.text_canvas.place(x=int(self.width * 0.45), y=0)
+ user_function = Frame(self, width=self.width * 0.2, height=self.height * 0.65)
+ user_function.place(x=int(self.width * 0.8), y=0)
+ self.user_function_canvas = Canvas(user_function, width=self.width * 0.19,
+ height=self.height * 0.65, bg="white",highlightthickness=0)
+ y_scrollbar = Scrollbar(user_function, orient="vertical", command=self.user_function_canvas.yview)
+ x_scrollbar = Scrollbar(user_function, orient="horizontal", command=self.user_function_canvas.xview)
+ x_scrollbar.pack(side=BOTTOM, fill=BOTH)
+ y_scrollbar.pack(side=RIGHT, fill=BOTH)
+ self.user_function_canvas.pack(side=TOP, fill=BOTH)
+ self.user_function_canvas.config(yscrollcommand=y_scrollbar.set, xscrollcommand=x_scrollbar.set)
+ self.user_function_canvas.config(scrollregion=self.user_function_canvas.bbox("all"))
+ self.create_form()
+
+
+if __name__ == '__main__':
+ root = Tk()
+ screenwidth = root.winfo_screenwidth()
+ screenheight = root.winfo_screenheight()
+ root_attr = {
+ "width": int(screenwidth * 1),
+ "height": int(screenheight * 1),
+ }
+ 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 = FunctionDisplay(root, width=root_attr["width"], height=root_attr["height"])
+ app.place(x=0, y=0, anchor=NW)
+ root.mainloop()
diff --git a/x5/basic.png b/x5/basic.png
new file mode 100644
index 0000000..2fa5dc7
Binary files /dev/null and b/x5/basic.png differ
diff --git a/x5/function.json b/x5/function.json
new file mode 100644
index 0000000..a8b70c4
--- /dev/null
+++ b/x5/function.json
@@ -0,0 +1 @@
+{"sin(x)": "sin(x)", "cos(x)": "cos(x)", "tan(x)": "tan(x)"}
\ No newline at end of file
diff --git a/x5/functionUtil.py b/x5/functionUtil.py
new file mode 100644
index 0000000..176e422
--- /dev/null
+++ b/x5/functionUtil.py
@@ -0,0 +1,63 @@
+import json
+import re
+import sys
+
+class FunctionUtil:
+ def __init__(self):
+ self.filename = sys.path[0]+"/./function.json"
+ self.data = {}
+ self.load()
+
+ def load(self):
+ """
+ 加载文件数据
+ """
+ try:
+ with open(self.filename, 'r', encoding="utf-8") as f:
+ self.data = json.load(f)
+ except FileNotFoundError:
+ pass
+
+ def save(self):
+ """
+ 将函数保存至json文件当中
+ """
+ with open(self.filename, "w", encoding="utf-8") as f:
+ json.dump(self.data, f)
+
+ def check_function_exit(self, function):
+ """
+ 检查用户输入的函数是否包含用户自定义函数
+ """
+ for key in self.data.keys():
+ if function.find(key) >=0:
+ return True
+ return False
+
+ def add_function(self, key, value):
+ """
+ 添加函数
+ """
+ self.data[key.strip()] = value.strip()
+ self.save()
+
+ def get_function_by_iter(self, key):
+ """
+ 遍历找出函数名所对应的函数体
+ """
+ result = key
+ for dict_key in self.data.keys():
+ if result.find(dict_key) >= 0:
+ value = result.replace(dict_key, "("+self.data[dict_key]+")")
+ result = self.replace_values_recursive(value)
+ return result
+
+ def replace_values_recursive(self, value):
+ """
+ 将键值对应的数学函数替换为实际函数
+ """
+ for key in self.data:
+ if key in value:
+ replacement = self.data[key]
+ value = "("+value.replace(key, replacement)+")"
+ return value
diff --git a/x5/image/下部背景.png b/x5/image/下部背景.png
new file mode 100644
index 0000000..f610758
Binary files /dev/null and b/x5/image/下部背景.png differ
diff --git a/x5/image/下部背景@2x.png b/x5/image/下部背景@2x.png
new file mode 100644
index 0000000..4117a49
Binary files /dev/null and b/x5/image/下部背景@2x.png differ
diff --git a/x5/image/下部背景@3x.png b/x5/image/下部背景@3x.png
new file mode 100644
index 0000000..ec4b13e
Binary files /dev/null and b/x5/image/下部背景@3x.png differ
diff --git a/x5/image/勾选.png b/x5/image/勾选.png
new file mode 100644
index 0000000..1f79713
Binary files /dev/null and b/x5/image/勾选.png differ
diff --git a/x5/image/勾选@2x.png b/x5/image/勾选@2x.png
new file mode 100644
index 0000000..218acdd
Binary files /dev/null and b/x5/image/勾选@2x.png differ
diff --git a/x5/image/勾选@3x.png b/x5/image/勾选@3x.png
new file mode 100644
index 0000000..7188964
Binary files /dev/null and b/x5/image/勾选@3x.png differ
diff --git a/x5/image/勾选选中.png b/x5/image/勾选选中.png
new file mode 100644
index 0000000..7924490
Binary files /dev/null and b/x5/image/勾选选中.png differ
diff --git a/x5/image/勾选选中@2x.png b/x5/image/勾选选中@2x.png
new file mode 100644
index 0000000..43afa0c
Binary files /dev/null and b/x5/image/勾选选中@2x.png differ
diff --git a/x5/image/勾选选中@3x.png b/x5/image/勾选选中@3x.png
new file mode 100644
index 0000000..7851730
Binary files /dev/null and b/x5/image/勾选选中@3x.png differ
diff --git a/x5/image/右侧背景.png b/x5/image/右侧背景.png
new file mode 100644
index 0000000..98e4b89
Binary files /dev/null and b/x5/image/右侧背景.png differ
diff --git a/x5/image/右侧背景@2x.png b/x5/image/右侧背景@2x.png
new file mode 100644
index 0000000..d508637
Binary files /dev/null and b/x5/image/右侧背景@2x.png differ
diff --git a/x5/image/右侧背景@3x.png b/x5/image/右侧背景@3x.png
new file mode 100644
index 0000000..7de0099
Binary files /dev/null and b/x5/image/右侧背景@3x.png differ
diff --git a/x5/image/导航背景.jpg b/x5/image/导航背景.jpg
new file mode 100644
index 0000000..275a004
Binary files /dev/null and b/x5/image/导航背景.jpg differ
diff --git a/x5/image/导航背景@2x.png b/x5/image/导航背景@2x.png
new file mode 100644
index 0000000..5122889
Binary files /dev/null and b/x5/image/导航背景@2x.png differ
diff --git a/x5/image/导航背景@3x.png b/x5/image/导航背景@3x.png
new file mode 100644
index 0000000..981a4b6
Binary files /dev/null and b/x5/image/导航背景@3x.png differ
diff --git a/x5/image/文字背景.png b/x5/image/文字背景.png
new file mode 100644
index 0000000..83d3134
Binary files /dev/null and b/x5/image/文字背景.png differ
diff --git a/x5/image/文字背景2.png b/x5/image/文字背景2.png
new file mode 100644
index 0000000..a114b1d
Binary files /dev/null and b/x5/image/文字背景2.png differ
diff --git a/x5/image/文字背景2@2x.png b/x5/image/文字背景2@2x.png
new file mode 100644
index 0000000..c7126bd
Binary files /dev/null and b/x5/image/文字背景2@2x.png differ
diff --git a/x5/image/文字背景2@3x.png b/x5/image/文字背景2@3x.png
new file mode 100644
index 0000000..267e8ef
Binary files /dev/null and b/x5/image/文字背景2@3x.png differ
diff --git a/x5/image/文字背景@2x.png b/x5/image/文字背景@2x.png
new file mode 100644
index 0000000..9f976a6
Binary files /dev/null and b/x5/image/文字背景@2x.png differ
diff --git a/x5/image/文字背景@3x.png b/x5/image/文字背景@3x.png
new file mode 100644
index 0000000..0c911a8
Binary files /dev/null and b/x5/image/文字背景@3x.png differ
diff --git a/x5/image/用户命名并新增基本函数-点击.png b/x5/image/用户命名并新增基本函数-点击.png
new file mode 100644
index 0000000..5c4b86b
Binary files /dev/null and b/x5/image/用户命名并新增基本函数-点击.png differ
diff --git a/x5/image/用户命名并新增基本函数-点击@2x.png b/x5/image/用户命名并新增基本函数-点击@2x.png
new file mode 100644
index 0000000..56a9e14
Binary files /dev/null and b/x5/image/用户命名并新增基本函数-点击@2x.png differ
diff --git a/x5/image/用户命名并新增基本函数-点击@3x.png b/x5/image/用户命名并新增基本函数-点击@3x.png
new file mode 100644
index 0000000..bb3cfa1
Binary files /dev/null and b/x5/image/用户命名并新增基本函数-点击@3x.png differ
diff --git a/x5/image/用户命名并新增基本函数.png b/x5/image/用户命名并新增基本函数.png
new file mode 100644
index 0000000..1e0f408
Binary files /dev/null and b/x5/image/用户命名并新增基本函数.png differ
diff --git a/x5/image/用户命名并新增基本函数@2x.png b/x5/image/用户命名并新增基本函数@2x.png
new file mode 100644
index 0000000..453249f
Binary files /dev/null and b/x5/image/用户命名并新增基本函数@2x.png differ
diff --git a/x5/image/用户命名并新增基本函数@3x.png b/x5/image/用户命名并新增基本函数@3x.png
new file mode 100644
index 0000000..1546a58
Binary files /dev/null and b/x5/image/用户命名并新增基本函数@3x.png differ
diff --git a/x5/image/背景.jpg b/x5/image/背景.jpg
new file mode 100644
index 0000000..6f0af51
Binary files /dev/null and b/x5/image/背景.jpg differ
diff --git a/x5/image/背景@2x.jpg b/x5/image/背景@2x.jpg
new file mode 100644
index 0000000..365e47c
Binary files /dev/null and b/x5/image/背景@2x.jpg differ
diff --git a/x5/image/背景@3x.jpg b/x5/image/背景@3x.jpg
new file mode 100644
index 0000000..356fb09
Binary files /dev/null and b/x5/image/背景@3x.jpg differ
diff --git a/x5/image/象限选择背景.png b/x5/image/象限选择背景.png
new file mode 100644
index 0000000..1ca972a
Binary files /dev/null and b/x5/image/象限选择背景.png differ
diff --git a/x5/image/象限选择背景@2x.png b/x5/image/象限选择背景@2x.png
new file mode 100644
index 0000000..c8f5b25
Binary files /dev/null and b/x5/image/象限选择背景@2x.png differ
diff --git a/x5/image/象限选择背景@3x.png b/x5/image/象限选择背景@3x.png
new file mode 100644
index 0000000..23c9601
Binary files /dev/null and b/x5/image/象限选择背景@3x.png differ
diff --git a/x5/image/输入条.png b/x5/image/输入条.png
new file mode 100644
index 0000000..adf0782
Binary files /dev/null and b/x5/image/输入条.png differ
diff --git a/x5/image/输入条@2x.png b/x5/image/输入条@2x.png
new file mode 100644
index 0000000..b2867de
Binary files /dev/null and b/x5/image/输入条@2x.png differ
diff --git a/x5/image/输入条@3x.png b/x5/image/输入条@3x.png
new file mode 100644
index 0000000..abafd68
Binary files /dev/null and b/x5/image/输入条@3x.png differ
diff --git a/x5/image/输出-点击.png b/x5/image/输出-点击.png
new file mode 100644
index 0000000..0d06be3
Binary files /dev/null and b/x5/image/输出-点击.png differ
diff --git a/x5/image/输出-点击@2x.png b/x5/image/输出-点击@2x.png
new file mode 100644
index 0000000..26c0c5a
Binary files /dev/null and b/x5/image/输出-点击@2x.png differ
diff --git a/x5/image/输出-点击@3x.png b/x5/image/输出-点击@3x.png
new file mode 100644
index 0000000..dc6f3ad
Binary files /dev/null and b/x5/image/输出-点击@3x.png differ
diff --git a/x5/image/输出.png b/x5/image/输出.png
new file mode 100644
index 0000000..833da41
Binary files /dev/null and b/x5/image/输出.png differ
diff --git a/x5/image/输出@2x.png b/x5/image/输出@2x.png
new file mode 100644
index 0000000..7f963ee
Binary files /dev/null and b/x5/image/输出@2x.png differ
diff --git a/x5/image/输出@3x.png b/x5/image/输出@3x.png
new file mode 100644
index 0000000..43357e1
Binary files /dev/null and b/x5/image/输出@3x.png differ
diff --git a/x5/image/长条输入框.png b/x5/image/长条输入框.png
new file mode 100644
index 0000000..13031d2
Binary files /dev/null and b/x5/image/长条输入框.png differ
diff --git a/x5/image/长条输入框@2x.png b/x5/image/长条输入框@2x.png
new file mode 100644
index 0000000..e53671b
Binary files /dev/null and b/x5/image/长条输入框@2x.png differ
diff --git a/x5/image/长条输入框@3x.png b/x5/image/长条输入框@3x.png
new file mode 100644
index 0000000..006b8b8
Binary files /dev/null and b/x5/image/长条输入框@3x.png differ
diff --git a/x5/test.py b/x5/test.py
new file mode 100644
index 0000000..3155f6f
--- /dev/null
+++ b/x5/test.py
@@ -0,0 +1,45 @@
+import tkinter as tk
+
+import numpy as np
+from matplotlib import pyplot as plt
+from matplotlib.figure import Figure
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+from mpl_toolkits.mplot3d import Axes3D
+import sympy
+from numpy import arange
+
+
+def plot_3d_graph():
+ # 创建一个 Figure 对象
+ fig = Figure(figsize=(8, 8), dpi=100, facecolor='#cdcdcd', edgecolor="#cdcdcd")
+ x = arange(-19, 20, 0.1)
+ y = arange(-19, 20, 0.1)
+ z = []
+ sympy.Symbol("x y")
+ for i in arange(-19, 20, 0.1):
+ z.append(sympy.sympify("x**2+y**2").subs("x", i).subs("y", i).evalf())
+ # 在 Figure 上创建一个 3D 子图
+ ax = fig.add_subplot(111, projection='3d')
+ ax.plot3D(x, y, z, 'gray')
+
+ # 绘制三维图形
+ # 在这里添加你自己的三维图形绘制逻辑
+ # 例如 ax.plot_surface() 或 ax.scatter()
+
+ # 创建一个 tkinter 窗口
+ root = tk.Tk()
+ root.title("3D Graph")
+
+ # 在 tkinter 窗口上创建一个 canvas
+ canvas = FigureCanvasTkAgg(fig, master=root)
+ canvas.draw()
+ canvas.get_tk_widget().pack()
+
+ # 运行 tkinter 主循环
+ tk.mainloop()
+
+
+# 调用函数绘制三维图形
+plot_3d_graph()
+
+
diff --git a/x5/test1.py b/x5/test1.py
new file mode 100644
index 0000000..e0aa54b
--- /dev/null
+++ b/x5/test1.py
@@ -0,0 +1,17 @@
+import tkinter as tk
+
+
+class MyCanvas(tk.Canvas):
+ def __init__(self, master=None, **kwargs):
+ super().__init__(master, **kwargs)
+
+ # 在画布上绘制一些文本
+ self.create_text(50, 50, text="Hello, Tkinter!")
+ self.create_text(100, 100, text="This is a text example.")
+
+
+if __name__ == "__main__":
+ root = tk.Tk()
+ canvas = MyCanvas(root, width=200, height=150)
+ canvas.pack()
+ root.mainloop()