matplotlib的功能及中文字体和数学符号等显示问题的处理
matplotlib的功能及中文字体和数学符号等显示问题的处理
matplotlib的功能及中文字体和数学符号等显示问题的处理
matplotlib的功能
matplotlib 是 Python 中一个非常强大的绘图库,广泛应用于数据可视化领域。跨平台兼容:支持 Windows/macOS/Linux
matplotlib的安装和基本情况,可参见 https://blog.csdn.net/cnds123/article/details/135904075
下面先简要介绍matplotlib的功能
基本模块
matplotlib.pyplot是 matplotlib 的核心模块,提供了一个类似于 MATLAB 的绘图接口,非常适合交互式绘图。
matplotlib.pyplot是 matplotlib 的核心模块,提供了一个类似于 MATLAB 的绘图接口,非常适合交互式绘图。这是最常用的模块,提供了类似MATLAB的绘图接口。
示例
import matplotlib.pyplot as plt
# 绘制一条简单的折线图
x = [1, 2, 3, 4, 5]
y = [1, 4, 9, 16, 25]
plt.plot(x, y, label="y = x^2") # 绘制折线图
plt.title("Simple Line Plot") # 设置标题
plt.xlabel("X-axis") # 设置X轴标签
plt.ylabel("Y-axis") # 设置Y轴标签
plt.legend() # 添加图例
plt.grid(True) # 添加网格
plt.show() # 显示图形
运行效果:
matplotlib.figure:
用于创建和管理整个图形容器(Figure对象),可以包含多个子图(Axes)。
顺便提示,当您使用 import matplotlib.pyplot as plt 后,可以直接通过 plt.figure() 创建图形对象,不需要额外导入 matplotlib.figure。只有在一些特殊情况下,比如您需要直接使用 Figure 类的特定方法或属性,或者在没有导入 pyplot 的情况下创建独立的 Figure 对象时,才需要明确导入 matplotlib.figure。【from matplotlib.figure import Figure 主要用于后端无关的图形创建,特别是在需要嵌入到其他GUI框架或Web应用中时使用。】
示例
import matplotlib.pyplot as plt
# 创建一个 Figure 对象
fig = plt.figure(figsize=(10, 5)) # figsize 设置图形大小
# 添加第一个子图
ax1 = fig.add_subplot(1, 2, 1) # 1行2列的第1个
ax1.plot([1, 2, 3], [1, 4, 9], 'r') # 绘制红色折线图
ax1.set_title("Subplot 1") # 设置子图标题
ax1.set_xlabel("X-axis") # 设置X轴标签
ax1.set_ylabel("Y-axis") # 设置Y轴标签
# 添加第二个子图
ax2 = fig.add_subplot(1, 2, 2) # 1行2列的第2个
ax2.bar([1, 2, 3], [1, 4, 9]) # 绘制柱状图
ax2.set_title("Subplot 2") # 设置子图标题
ax2.set_xlabel("X-axis") # 设置X轴标签
ax2.set_ylabel("Y-axis") # 设置Y轴标签
plt.show() # 显示图形
运行效果:
matplotlib.axes:表示图形中的一个绘图区域,表示具体的绘图区域,提供更精细的控制,可以设置坐标轴范围、标题、标签等。
示例
import matplotlib.pyplot as plt
# 创建一个 Figure 和一个 Axes
fig, ax = plt.subplots()
# 绘制散点图
x = [1, 2, 3, 4, 5]
y = [1, 4, 9, 16, 25]
ax.scatter(x, y, color='blue', marker='o') # 绘制蓝色圆点散点图
# 设置坐标轴范围
ax.set_xlim(0, 6) # X轴范围
ax.set_ylim(0, 30) # Y轴范围
# 设置标题和标签
ax.set_title("Scatter Plot")
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
# 添加网格
ax.grid(True)
plt.show() # 显示图形
运行效果:
【pyplot 模块已经包含了创建和管理 Figure 和 Axes 对象的所有常用功能。
通常只需要 import matplotlib.pyplot as plt 就足够了。
直接导入 matplotlib.figure 或 matplotlib.axes 主要用于高级自定义或特殊场景。】
高级模块
mplot3d:3D 绘图(曲面、散点、柱状图等)
示例:三维曲面图
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # 导入3D绘图模块
# 创建数据
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2)) # 创建一个正弦曲面
# 创建图形和3D坐标轴
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d') # 指定为3D坐标轴
# 绘制曲面图
ax.plot_surface(X, Y, Z, cmap='viridis') # 使用颜色映射
# 设置标题和标签
ax.set_title("3D Surface Plot")
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
ax.set_zlabel("Z-axis")
plt.show()
运行效果:
FuncAnimation:动画支持
示例:简单的动画
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# 创建图形和坐标轴
fig, ax = plt.subplots()
x = np.linspace(0, 2 * np.pi, 100)
line, = ax.plot(x, np.sin(x)) # 初始曲线
# 更新函数
def update(frame):
line.set_ydata(np.sin(x + frame / 10)) # 更新曲线的 y 值
return line, # 返回更新的对象
# 创建动画
ani = FuncAnimation(fig, update, frames=range(100), blit=True)
# 显示动画
plt.show()
运行效果:
其它
支持中文显示,但需要进行一些显式配置:
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS'] # macOS
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示异常
完美兼容 NumPy、Pandas、SciPy
常用函数的语法和作用
plt.title(label, fontdict=None, loc='center', pad=None, **kwargs)
作用
为当前图表添加标题。
参数
label:标题文本(字符串)。
fontdict:可选,字典类型,用于设置字体属性(如大小、颜色等),如 {'fontsize':14, 'color':'red'}。
loc:可选,标题位置,取值为 'center'(默认)、'left'、'right'。
pad:可选,标题与图表顶部的间距(浮点数)。单位为点(points)。
**kwargs:其他可选参数,例如 fontsize、color 等,如 fontsize=12, color='blue'。
示例
plt.title('正弦函数图像', fontdict={'fontsize': 16, 'color': 'blue'})
plt.xlabel(xlabel, fontdict=None, labelpad=None, **kwargs)
作用
为 X 轴添加标签。
参数
xlabel:标签文本(字符串)。
fontdict:可选,设置字体属性。
labelpad:可选,标签与坐标轴( X 轴)的间距,单位为点(points)。
**kwargs:其他可选参数,例如 fontsize、color 等。
示例
plt.xlabel('时间 (秒)', fontdict={'fontsize': 12})
plt.ylabel(ylabel, fontdict=None, labelpad=None, **kwargs)
作用
为 Y 轴添加标签。
参数
与 plt.xlabel() 相同。
示例
plt.ylabel('温度 (°C)', rotation=0, labelpad=20) # rotation=0 让标签水平显示
plt.plot(*args, scalex=True, scaley=True, data=None, **kwargs)
作用
绘制折线图或散点图。
参数
*args:可变参数,支持多种形式:
x, y:X 和 Y 坐标数组(如 plt.plot([1,2,3], [4,5,6]))。
y:仅 Y 坐标(此时 X 默认为 [0,1,2,...])。
x, y, format_string:指定线条样式(如 'r--' 表示红色虚线)。
scalex 和 scaley:布尔值,是否调整 x 轴和 y 轴的范围以适应数据。
data:数据源,可以是一个 Pandas DataFrame 或其他数据结构。
**kwargs:其他可选参数,用于自定义线条的样式,例如:
color/c:线条颜色。
linestyle/ls:线条样式,如 '-'(实线)、'--'(虚线)、'-.'(点划线)等。
linewidth/lw:线宽
marker:数据点的标记样式,如 'o'(圆圈)、's'(正方形)、'*'(星号)等。
markersize/ms:标记大小
label:图例标签。
示例
x = [0, 1, 2, 3, 4]
y = [0, 2, 4, 6, 8]
plt.plot(x, y, color='red', linestyle='--', marker='o', label='Line 1')
plt.text(x, y, s, fontdict=None, withdash=False, **kwargs)
作用
在图表中指定位置添加文本。
参数
x, y:文本位置的坐标(浮点数)。
s:文本内容(字符串)。
fontdict:可选,设置字体属性。
**kwargs:其他属性,如 rotation(旋转角度)、ha(水平对齐)、va(垂直对齐)等。
fontsize:文本的字体大小。
color:文本的颜色。
ha(水平对齐方式):可选值为 'left'、'center'、'right'。
va(垂直对齐方式):可选值为 'top'、'center'、'bottom'。
rotation:旋转角度
示例
plt.text(2, 5, 'v₀ = 80 m/s', fontsize=12, color='blue', ha='center', va='bottom')
matplotlib中文字体和数学符号等显示问题的处理
下面着重介绍matplotlib中文字体和数学符号等显示方面确实容易出现报错或显示为方框□问题。
先看一个示例
源码:
import matplotlib.pyplot as plt
import numpy as np
# 设置中文字体,解决运行报错或显示为方框□问题
plt.rcParams["font.family"] = ["SimHei","Microsoft YaHei", "KaiTi", "FangSong"]
# 解决负号显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
# 生成数据
x = np.linspace(0, 2*np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
# 创建图形和子图
plt.figure(figsize=(10, 6))
# 绘制正弦曲线
plt.plot(x, y1, 'b-', label=r'$\alpha_i=\sin(\theta_i)$') # (使用 LaTeX 语法)包含下标和希腊字母
# 绘制余弦曲线
plt.plot(x, y2, 'r--', label=r'$\beta^2=\cos^2(\phi)$') #(使用 LaTeX 语法) 包含上标和希腊字母
# 添加标题和标签
plt.title('中文字体测试:正弦和余弦函数')
plt.xlabel('X轴:弧度')
plt.ylabel('Y轴:函数值')
# 添加图例(包含数学表达式)
plt.legend(loc='upper right')
# 添加文本注释(包含上下标和根号)
plt.text(3.5, 0.6, r'$\sqrt{x^2 + y^2}$', fontsize=15)
plt.text(3.5, 0.4, r'$x_{min}=0$', fontsize=15)
plt.text(3.5, 0.3, r'$y_{max}=1$', fontsize=15)
plt.text(3.5, 0.1, r'$y = \frac{1}{2}gt^2$',fontsize=15) # 分数
# 设置网格
plt.grid(True)
# 显示图形
plt.show()
说明,在代码中,你看到的 r'$...$' 格式就是 LaTeX 数学模式的用法。下面简要解释:
基本语法规则
在 Matplotlib 中使用 LaTeX 语法时,需要注意:
- 用美元符号 $ 包裹表达式:例如 r'$\alpha$' 会渲染为希腊字母 α。
- 原始字符串(Raw String):字符串前加 r,避免 Python 转义特殊字符(如 \)。
- 支持标准 LaTeX 命令:如 \sqrt(根号)、^(上标)、_(下标)等。
常见数学符号与命令
上标使用 ^,例如:
r'$x^2$' # 渲染为 x²
r'$e^{i\pi}$' # 渲染为 e^(iπ)
下标使用 _,例如:
r'$x_{min}$' # 渲染为 xₘᵢₙ
r'$\sum_{i=1}^n$' # 渲染为求和符号,下标 i=1,上标 n
组合使用:
r'$A_{ij}^2$' # 渲染为 Aᵢⱼ²
等等
将 Matplotlib 图表嵌入到 Tkinter 窗口的例子
可以使用 Tkinter 结合 Matplotlib 开发程序,并将 Matplotlib 图表嵌入到 Tkinter 窗口中。这种组合允许你创建图形用户界面(GUI),并在其中显示和交互式地更新图表——实现“数据可视化+交互控制”一体化界面。
下是一个简单示例,将正弦函数图像嵌入tkinter窗口的示例,支持实时调节参数并更新图表。先给出运行效果:
源码如下:
import tkinter as tk
from tkinter import ttk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import numpy as np
# 设置matplotlib支持中文显示
plt.rcParams["font.family"] = ["SimHei", "Microsoft YaHei"]
class MatplotlibInTkinterApp:
def __init__(self, root):
self.root = root
self.root.title("Matplotlib 嵌入 Tkinter 示例")
self.root.geometry("900x600")
# 创建界面布局
self.create_widgets()
self.init_plot()
def create_widgets(self):
"""创建界面控件"""
# 左侧控制面板
control_frame = tk.Frame(self.root, width=250, bg="#f0f0f0")
control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)
control_frame.pack_propagate(False) # 防止控件自动调整大小
# 右侧绘图区域
self.plot_frame = tk.Frame(self.root, bg="white")
self.plot_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)
# 左侧控件:参数调节
tk.Label(control_frame, text="函数参数调节", font=("Arial", 12, "bold")).pack(pady=10)
# 频率调节
tk.Label(control_frame, text="频率 (Hz):").pack(anchor=tk.W, padx=15, pady=5)
self.freq_var = tk.DoubleVar(value=1.0)
freq_scale = tk.Scale(control_frame, from_=0.1, to=5.0, resolution=0.1,
orient=tk.HORIZONTAL, variable=self.freq_var,
command=self.update_plot)
freq_scale.pack(fill=tk.X, padx=15, pady=5)
# 幅值调节
tk.Label(control_frame, text="幅值:").pack(anchor=tk.W, padx=15, pady=5)
self.amp_var = tk.DoubleVar(value=1.0)
amp_scale = tk.Scale(control_frame, from_=0.1, to=3.0, resolution=0.1,
orient=tk.HORIZONTAL, variable=self.amp_var,
command=self.update_plot)
amp_scale.pack(fill=tk.X, padx=15, pady=5)
# 相位调节
tk.Label(control_frame, text="相位 (度):").pack(anchor=tk.W, padx=15, pady=5)
self.phase_var = tk.DoubleVar(value=0)
phase_scale = tk.Scale(control_frame, from_=0, to=360, resolution=10,
orient=tk.HORIZONTAL, variable=self.phase_var,
command=self.update_plot)
phase_scale.pack(fill=tk.X, padx=15, pady=5)
# 重置按钮
reset_btn = tk.Button(control_frame, text="重置参数", command=self.reset_params,
bg="#4CAF50", fg="white", font=("Arial", 10))
reset_btn.pack(pady=15)
def init_plot(self):
"""初始化图表"""
# 创建matplotlib的Figure和Axes对象
self.fig, self.ax = plt.subplots(figsize=(7, 5), dpi=100, facecolor="white")
self.ax.set_title("正弦函数图像", fontsize=14)
self.ax.set_xlabel("x (弧度)")
self.ax.set_ylabel("y")
self.ax.grid(True, alpha=0.3)
# 创建Canvas并嵌入到tkinter
self.canvas = FigureCanvasTkAgg(self.fig, master=self.plot_frame)
self.canvas.draw()
canvas_widget = self.canvas.get_tk_widget()
canvas_widget.pack(fill=tk.BOTH, expand=True)
# 添加工具栏
toolbar_frame = tk.Frame(self.plot_frame)
toolbar_frame.pack(side=tk.TOP, fill=tk.X)
toolbar = NavigationToolbar2Tk(self.canvas, toolbar_frame)
toolbar.update()
# 初始绘图
self.update_plot()
def update_plot(self, *args):
"""更新图表数据"""
# 获取参数
freq = self.freq_var.get()
amp = self.amp_var.get()
phase = np.radians(self.phase_var.get())
# 生成数据
x = np.linspace(-4*np.pi, 4*np.pi, 1000)
y = amp * np.sin(freq * x + phase)
# 清除旧图表并绘制新图表
self.ax.clear()
self.ax.plot(x, y, color="#2196F3", linewidth=2)
self.ax.set_title(f"y = {amp}·sin({freq}x + {phase*180/np.pi:.0f}°)", fontsize=12)
self.ax.set_xlabel("x (弧度)")
self.ax.set_ylabel("y")
self.ax.grid(True, alpha=0.3)
self.ax.set_xlim(-4*np.pi, 4*np.pi)
self.ax.set_ylim(-amp*1.2, amp*1.2)
# 刷新画布
self.canvas.draw()
def reset_params(self):
"""重置参数"""
self.freq_var.set(1.0)
self.amp_var.set(1.0)
self.phase_var.set(0)
self.update_plot()
# 运行程序
if __name__ == "__main__":
root = tk.Tk()
app = MatplotlibInTkinterApp(root)
root.mainloop()
更改扩充上面代码功能
先看运行图:
源码如下:
import tkinter as tk
from tkinter import ttk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
class DataVisualizationApp:
def __init__(self):
self.root = tk.Tk()
self.root.title("数据可视化工具")
self.root.geometry("1000x700")
# 设置matplotlib参数
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
self.create_layout()
self.create_left_panel()
self.create_right_panel()
def create_layout(self):
"""创建主要布局"""
# 左侧面板 - 固定宽度
self.left_frame = tk.Frame(self.root, width=300, bg="#f8f9fa")
self.left_frame.pack(side="left", fill="y", padx=5, pady=5)
self.left_frame.pack_propagate(False)
# 右侧面板
self.right_frame = tk.Frame(self.root, bg="white")
self.right_frame.pack(side="right", fill="both", expand=True, padx=5, pady=5)
def create_left_panel(self):
"""创建左侧控制面板"""
# === 控制参数区域 ===
control_frame = tk.LabelFrame(self.left_frame, text="控制参数",
font=("Microsoft YaHei", 11, "bold"),
fg="#ff6600", bg="#f8f9fa")
control_frame.pack(fill="x", padx=10, pady=10)
# 配置列权重
control_frame.columnconfigure(1, weight=1)
# 函数类型选择
tk.Label(control_frame, text="函数类型:", bg="#f8f9fa").grid(
row=0, column=0, sticky="w", padx=5, pady=8)
self.func_var = tk.StringVar(value="sin")
func_combo = ttk.Combobox(control_frame, textvariable=self.func_var,
values=["sin", "cos", "tan", "exp"],
width=20, state="readonly")
func_combo.grid(row=0, column=1, padx=5, pady=8, sticky="ew")
func_combo.bind("<<ComboboxSelected>>", self.update_plot)
# 频率调节
freq_frame = tk.Frame(control_frame, bg="#f8f9fa")
freq_frame.grid(row=1, column=0, columnspan=2, sticky="ew", padx=5, pady=5)
freq_frame.columnconfigure(1, weight=1)
tk.Label(freq_frame, text="频率:", bg="#f8f9fa").grid(row=0, column=0, sticky="w")
self.freq_var = tk.DoubleVar(value=1.0)
self.freq_label = tk.Label(freq_frame, text="1.0", bg="#f8f9fa", fg="#333")
self.freq_label.grid(row=0, column=2, sticky="e", padx=(10,0))
freq_scale = tk.Scale(freq_frame, from_=0.1, to=5.0, resolution=0.1,
orient="horizontal", variable=self.freq_var,
command=self.on_freq_change, showvalue=0, bg="#f8f9fa")
freq_scale.grid(row=1, column=0, columnspan=3, sticky="ew", pady=2)
# 幅值调节
amp_frame = tk.Frame(control_frame, bg="#f8f9fa")
amp_frame.grid(row=2, column=0, columnspan=2, sticky="ew", padx=5, pady=5)
amp_frame.columnconfigure(1, weight=1)
tk.Label(amp_frame, text="幅值:", bg="#f8f9fa").grid(row=0, column=0, sticky="w")
self.amp_var = tk.DoubleVar(value=1.0)
self.amp_label = tk.Label(amp_frame, text="1.0", bg="#f8f9fa", fg="#333")
self.amp_label.grid(row=0, column=2, sticky="e", padx=(10,0))
amp_scale = tk.Scale(amp_frame, from_=0.1, to=3.0, resolution=0.1,
orient="horizontal", variable=self.amp_var,
command=self.on_amp_change, showvalue=0, bg="#f8f9fa")
amp_scale.grid(row=1, column=0, columnspan=3, sticky="ew", pady=2)
# 相位调节
phase_frame = tk.Frame(control_frame, bg="#f8f9fa")
phase_frame.grid(row=3, column=0, columnspan=2, sticky="ew", padx=5, pady=5)
phase_frame.columnconfigure(1, weight=1)
tk.Label(phase_frame, text="相位:", bg="#f8f9fa").grid(row=0, column=0, sticky="w")
self.phase_var = tk.DoubleVar(value=0.0)
self.phase_label = tk.Label(phase_frame, text="0°", bg="#f8f9fa", fg="#333")
self.phase_label.grid(row=0, column=2, sticky="e", padx=(10,0))
phase_scale = tk.Scale(phase_frame, from_=0, to=360, resolution=10,
orient="horizontal", variable=self.phase_var,
command=self.on_phase_change, showvalue=0, bg="#f8f9fa")
phase_scale.grid(row=1, column=0, columnspan=3, sticky="ew", pady=2)
# 重置按钮
reset_btn = tk.Button(control_frame, text="重置参数", command=self.reset_params,
bg="#4CAF50", fg="white", font=("Microsoft YaHei", 10, "bold"),
cursor="hand2", width=12)
reset_btn.grid(row=4, column=0, columnspan=2, pady=15)
# === 信息说明区域 - 确保显示竖直滚动条 ===
info_frame = tk.LabelFrame(self.left_frame, text="信息说明",
font=("Microsoft YaHei", 11, "bold"),
fg="#333333", bg="#f8f9fa")
info_frame.pack(fill="both", expand=True, padx=10, pady=10)
# 创建scrolledtext风格的文本区域
text_frame = tk.Frame(info_frame, bg="#f8f9fa")
text_frame.pack(fill="both", expand=True, padx=5, pady=5)
# 配置grid权重
text_frame.grid_rowconfigure(0, weight=1)
text_frame.grid_columnconfigure(0, weight=1)
# 文本框
self.info_text = tk.Text(text_frame,
wrap="word",
font=("Microsoft YaHei", 9),
bg="white",
relief="sunken",
borderwidth=2,
padx=8,
pady=5)
self.info_text.grid(row=0, column=0, sticky="nsew")
# 竖直滚动条
v_scrollbar = tk.Scrollbar(text_frame,
orient="vertical",
command=self.info_text.yview,
cursor="hand2",
width=18, # 加宽滚动条
bg="#d0d0d0",
troughcolor="#f0f0f0",
activebackground="#a0a0a0")
v_scrollbar.grid(row=0, column=1, sticky="ns")
# 绑定滚动条
self.info_text.config(yscrollcommand=v_scrollbar.set)
# 添加说明文本
self.update_info_text()
self.info_text.config(state="disabled")
## # 方案一问题:图像显示不完整
## def create_right_panel(self):
## """创建右侧matplotlib绘图区域 - 修复边缘显示问题"""
## # 创建matplotlib图形
## self.fig, self.ax = plt.subplots(figsize=(8, 5), facecolor='white', dpi=100)
##
## # 关键修复:调整子图边距,确保图表完整显示包括边框
## self.fig.subplots_adjust(
## left=0.08, # 左边距
## right=0.95, # 右边距 - 这个值看右边显示
## top=0.90, # 顶边距
## bottom=0.23 # 底边距 - 这个值看下边显示
## )
##
## # 创建Canvas
## self.canvas = FigureCanvasTkAgg(self.fig, master=self.right_frame)
##
## # Canvas布局 - 调整padding确保边框显示
## canvas_widget = self.canvas.get_tk_widget()
## canvas_widget.pack(fill="both", expand=True, padx=8, pady=60) # 增加padding
##
## # 初始化绘图
## self.update_plot()
# 方案二:图像显示完整
def create_right_panel(self):
"""方案二:简洁有效的解决方案"""
self.fig, self.ax = plt.subplots(figsize=(8, 5), facecolor='white', dpi=100)
# 这一行代码?
#self.fig.tight_layout(pad=3.5)
self.canvas = FigureCanvasTkAgg(self.fig, master=self.right_frame)
canvas_widget = self.canvas.get_tk_widget()
canvas_widget.pack(fill="both", expand=True, padx=10, pady=10)
# 关键的事件绑定
canvas_widget.bind('<Map>', lambda e: self.root.after(50, self.update_plot))
def on_freq_change(self, value):
"""频率变化回调"""
self.freq_label.config(text=f"{float(value):.1f}")
self.update_plot()
def on_amp_change(self, value):
"""幅值变化回调"""
self.amp_label.config(text=f"{float(value):.1f}")
self.update_plot()
def on_phase_change(self, value):
"""相位变化回调"""
self.phase_label.config(text=f"{int(float(value))}°")
self.update_plot()
def update_info_text(self):
"""更新信息说明"""
self.info_text.config(state="normal")
self.info_text.delete("1.0", "end")
info = """数学函数可视化工具
使用说明:
1. 选择函数类型(sin, cos, tan, exp)
2. 调节频率改变函数周期性质
3. 调节幅值改变函数振幅大小
4. 调节相位改变函数偏移量
参数说明:
• 频率:控制函数周期性变化的快慢
- 值越大,函数变化越快
- 对应函数中x的系数
• 幅值:控制函数最大值的大小
- 决定函数图像的高度
- 对应函数前面的系数
• 相位:控制函数在x轴上的偏移
- 以度为单位(0°-360°)
- 正值表示左移,负值表示右移
函数类型介绍:
sin:正弦函数,标准的波形函数
cos:余弦函数,相位偏移的正弦函数
tan:正切函数,具有垂直渐近线
exp:指数函数,呈指数增长或衰减
实时预览:
参数改变时图表会自动更新,方便观察函数变化规律。可以通过调节不同参数来理解它们对函数图像的影响。
操作技巧:
• 可以组合调节多个参数观察效果
• 使用重置按钮快速恢复默认设置
• 观察不同函数类型的特点和差异
• 理解数学函数的几何意义
应用场景:
• 数学教学和学习
• 信号处理基础概念
• 波形分析和理解
• 函数变换的可视化学习
"""
self.info_text.insert("1.0", info)
self.info_text.config(state="disabled")
def update_plot(self, *args):
"""更新图表 - 确保完整显示"""
# 清除之前的图
self.ax.clear()
# 获取参数
func_type = self.func_var.get()
freq = self.freq_var.get()
amp = self.amp_var.get()
phase = np.radians(self.phase_var.get())
# 生成数据
if func_type in ["sin", "cos"]:
periods = max(3, int(freq * 2))
x_range = periods * 2 * np.pi / freq
x = np.linspace(-x_range, x_range, 2000)
else:
x = np.linspace(-4*np.pi, 4*np.pi, 2000)
if func_type == "sin":
y = amp * np.sin(freq * x + phase)
title = f"y = {amp:.1f} × sin({freq:.1f}x + {self.phase_var.get():.0f}°)"
elif func_type == "cos":
y = amp * np.cos(freq * x + phase)
title = f"y = {amp:.1f} × cos({freq:.1f}x + {self.phase_var.get():.0f}°)"
elif func_type == "tan":
y = amp * np.tan(freq * x + phase)
y = np.clip(y, -10*amp, 10*amp)
title = f"y = {amp:.1f} × tan({freq:.1f}x + {self.phase_var.get():.0f}°)"
elif func_type == "exp":
y = amp * np.exp(freq * x + phase)
y = np.clip(y, -100*amp, 100*amp)
title = f"y = {amp:.1f} × exp({freq:.1f}x + {self.phase_var.get():.0f}°)"
# 绘制图形
self.ax.plot(x, y, linewidth=2.5, color='#2196F3', alpha=0.8)
self.ax.grid(True, alpha=0.3, linestyle='--')
self.ax.set_xlabel("x", fontsize=12)
self.ax.set_ylabel("y", fontsize=12)
self.ax.set_title(title, fontsize=14, color='#ff6600', pad=20)
# 设置坐标轴范围
if func_type in ["sin", "cos"]:
periods = max(3, int(freq * 2))
x_range = periods * 2 * np.pi / freq
self.ax.set_xlim(-x_range, x_range)
self.ax.set_ylim(-amp*1.2, amp*1.2)
elif func_type == "tan":
self.ax.set_xlim(-2*np.pi, 2*np.pi)
self.ax.set_ylim(-3*amp, 3*amp)
else:
self.ax.set_xlim(-2, 2)
y_max = max(10, amp*3)
self.ax.set_ylim(-y_max, y_max)
# 设置刻度
self.ax.tick_params(axis='both', which='major', labelsize=10)
# 强制更新布局 - 确保边框完整显示
self.fig.canvas.draw()
def reset_params(self):
"""重置所有参数"""
self.freq_var.set(1.0)
self.amp_var.set(1.0)
self.phase_var.set(0.0)
self.func_var.set("sin")
self.freq_label.config(text="1.0")
self.amp_label.config(text="1.0")
self.phase_label.config(text="0°")
self.update_plot()
def run(self):
"""运行应用程序"""
self.root.mainloop()
# 运行应用
if __name__ == "__main__":
app = DataVisualizationApp()
app.run()
注意:其中create_right_panel(self) 这个函数,方案二的代码,解决了方案一(代码已被注释掉)图像显示不完整问题!
【方案一图像显示不完整,表现为程序打开时,图像的边侧部分被遮挡显示不出来,但点击全屏后显示是正常的,全屏后还原显示也是正常。】
更多推荐
所有评论(0)