You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于复杂Matplotlib代码构建Tkinter页面以显示绘图

Tkinter集成Matplotlib复杂绘图实现

要实现点击按钮显示复杂Matplotlib绘图的Tkinter界面,核心是将Matplotlib的绘图逻辑嵌入Tkinter窗口,以下是完整实现方案:

实现步骤

  • 导入Tkinter及Matplotlib的Tk后端模块,替代直接使用pyplot的全局绘图方式
  • 将原有Matplotlib绘图逻辑封装为函数,使用matplotlib.figure.Figure创建绘图对象
  • 创建Tkinter主窗口,添加触发按钮,点击按钮时调用绘图函数并将画布嵌入窗口

完整代码

import math
import numpy
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk

# 原有的Panel类保持不变
class Panel:
    def __init__(self, xa, ya, xb, yb):
        self.xa, self.ya = xa, ya
        self.xb, self.yb = xb, yb
        self.xc, self.yc = (xa + xb) / 2, (ya + yb) / 2  
        self.length = math.sqrt((xb - xa)**2 + (yb - ya)**2) 
        if xb - xa <= 0.:
            self.beta = math.acos((yb - ya) / self.length)
        elif xb - xa > 0.:
            self.beta = math.pi + math.acos(-(yb - ya) / self.length)
        self.sigma = 1000.0  # source strength
        self.vt = 1.0  # tangential velocity
        self.cp = 1.0  # pressure coefficient

# 原有的Source类保持不变
class Source:
    def __init__(self, strength, x, y):
        self.strength = strength
        self.x, self.y = x, y
    
    def velocity(self, X, Y):
        u = (self.strength / (2 * math.pi) * (self.x - X) / (X **2 + Y **2))
        v = (self.strength / (2 * math.pi) * (self.y - Y) / (X **2 + Y **2))
        return u, v
    
    def stream_function(self, X, Y):
        psi = (self.strength / (2 * math.pi) *
               numpy.arctan2((Y - self.y), (X - self.x)))
        return psi

# 封装绘图函数,用于按钮点击触发
def plot_complex_figure(frame):
    # 清空之前的画布,避免重复绘制
    for widget in frame.winfo_children():
        widget.destroy()
    
    # 原有绘图数据计算逻辑
    u_inf = 5.0    
    N = 500 
    R = 5
    x_center, y_center = 0.0, 0.0
    theta = numpy.linspace(0.0, 2 * math.pi, 100)
    x_cylinder, y_cylinder = (x_center + R * numpy.cos(theta),
                              y_center + R * numpy.sin(theta))
    x_start, x_end = -10.1, 10.1           
    y_start, y_end = -10.1, 10.1           
    x = numpy.linspace(x_start, x_end, N)   
    y = numpy.linspace(y_start, y_end, N)   
    X, Y = numpy.meshgrid(x, y)             
    
    strength_source = 5.0                 
    x_source, y_source = 0.0, 0.0          
    source = Source(strength_source,x_source, y_source)
    u1, v1 = source.velocity(X, Y)
    psi1 = source.stream_function(X, Y)
    source_image = Source(strength_source, x_source, -y_source)
    u2, v2 = source_image.velocity(X, Y)
    psi2 = source_image.stream_function(X, Y)
    
    N_panels = 100  
    x_ends = R * numpy.cos(numpy.linspace(0.0, 2 * math.pi, N_panels + 1))
    y_ends = R * numpy.sin(numpy.linspace(0.0, 2 * math.pi, N_panels + 1))
    panels = numpy.empty(N_panels, dtype=object)
    for i in range(N_panels):
        panels[i] = Panel(x_ends[i], y_ends[i], x_ends[i + 1], y_ends[i + 1])
    
    u = u1 + u2
    v = v1 + v2
    psi = psi1 + psi2
    
    # 创建Matplotlib Figure对象,替代pyplot.figure
    size = 12
    fig = Figure(figsize=(size, size))
    ax = fig.add_subplot(111)
    
    # 在子图上绘制所有元素
    ax.grid()
    ax.set_xlabel('x', fontsize=16)
    ax.set_ylabel('y', fontsize=16)
    ax.plot(x_cylinder, y_cylinder, color='b', linestyle='-', linewidth=1)
    ax.plot(x_ends, y_ends, color='#CD2305', linestyle='-', linewidth=2)
    ax.scatter([p.xa for p in panels], [p.ya for p in panels],
               color='#CD2305', s=40)
    ax.scatter([p.xc for p in panels], [p.yc for p in panels],
               color='k', s=40, zorder=3)
    ax.legend(loc='best', prop={'size':16})
    ax.streamplot(X, Y, u, v, density=4, linewidth=0.6, arrowsize=2, arrowstyle='->')
    ax.set_xlim(-10.1, 10.1)
    ax.set_ylim(-10.1, 10.1)
    
    # 将Figure转换为Tkinter可用的画布
    canvas = FigureCanvasTkAgg(fig, master=frame)
    canvas.draw()
    # 添加Matplotlib工具栏,不需要可注释
    toolbar = NavigationToolbar2Tk(canvas, frame)
    toolbar.update()
    # 将画布显示在窗口中
    canvas.get_tk_widget().pack(fill=tk.BOTH, expand=1)

# 创建Tkinter主窗口
root = tk.Tk()
root.title("Matplotlib绘图演示")

# 创建按钮和绘图区域
button_frame = tk.Frame(root)
button_frame.pack(pady=10)
plot_btn = tk.Button(button_frame, text="显示复杂绘图", command=lambda: plot_complex_figure(plot_frame))
plot_btn.pack()

plot_frame = tk.Frame(root)
plot_frame.pack(fill=tk.BOTH, expand=1)

# 启动Tkinter事件循环
root.mainloop()

关键说明

  • 使用matplotlib.figure.Figure创建绘图对象,避免依赖pyplot的全局状态,更适配GUI嵌入场景
  • FigureCanvasTkAgg负责将Matplotlib的Figure转换为Tkinter可识别的组件
  • 按钮点击时先清空绘图区域再重新绘制,避免重复叠加
  • 可选的NavigationToolbar2Tk提供缩放、平移等标准绘图操作工具,无需可直接注释

内容的提问来源于stack exchange,提问作者Bryant Hernandez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:46:16