【问题标题】:How to get (3d) interactivity to work while embedding a matplotlib figure in a tkinter canvas如何在 tkinter 画布中嵌入 matplotlib 图形时获得(3d)交互性
【发布时间】:2020-10-29 17:51:28
【问题描述】:

我在 tkinter gui 画布中嵌入了 3D matplotlib 图,但无法使(鼠标)交互性(旋转/缩放等)工作。如果我只使用“pyplot.show()”命令而不嵌入 tk 交互工作,我是否必须手动设置所有回调才能使用 tkinter 嵌入或有简单的方法吗?

显示立方体的简单示例脚本:

import tkinter as tk
from tkinter.ttk import *

import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib import pyplot
from mpl_toolkits import mplot3d

import numpy
from stl import mesh


tk_root = tk.Tk()

figure = pyplot.figure()
axes = mplot3d.Axes3D(figure)

data = numpy.zeros(6, dtype=mesh.Mesh.dtype)
data['vectors'][0] = numpy.array([[0, 1, 1],[1, 0, 1],[0, 0, 1]])
data['vectors'][1] = numpy.array([[1, 0, 1],[0, 1, 1],[1, 1, 1]])
data['vectors'][2] = numpy.array([[1, 0, 0],[1, 0, 1],[1, 1, 0]])
data['vectors'][3] = numpy.array([[1, 1, 1],[1, 0, 1],[1, 1, 0]])
data['vectors'][4] = numpy.array([[0, 0, 0],[1, 0, 0],[1, 0, 1]])
data['vectors'][5] = numpy.array([[0, 0, 0],[0, 0, 1],[1, 0, 1]])
msh = mesh.Mesh(data)

axes.add_collection3d(mplot3d.art3d.Poly3DCollection(msh.vectors))
# pyplot.show()

canvas = FigureCanvasTkAgg(figure, tk_root)
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas, tk_root)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

tk_root.mainloop()

【问题讨论】:

    标签: python matplotlib tkinter 3d interactive


    【解决方案1】:

    已接受的答案是您问题的有效解决方案,但我建议不要将 pyplot 与 tkinter 一起使用,因为它会导致我自己不理解的各种问题(例如:关闭 tkinter 窗口将使 pyplot 继续运行)。相反,我会做这样的事情:

    import tkinter as tk
    import numpy as np
    import matplotlib
    matplotlib.use("TkAgg")
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    from matplotlib.figure import Figure
    
    
    data=np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    X=np.array([[0, 1, 2], [0, 1, 2], [0, 1, 2]])
    Y=np.array([[2, 2, 2], [1, 1, 1], [0, 0, 0]])
    tk_root = tk.Tk()
    
    figure = Figure(figsize=(12, 8))
    ax= figure.add_subplot(1, 1, 1, projection='3d')
    ax.plot_surface(data, X, Y, shade=True)
    canvas = FigureCanvasTkAgg(figure, tk_root)
    canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
    canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
    canvas.mpl_connect('button_press_event', ax._button_press)
    canvas.mpl_connect('button_release_event', ax._button_release)
    canvas.mpl_connect('motion_notify_event', ax._on_move)
    
    tk_root.mainloop()
    

    我知道这个答案并不完全符合你的问题,但这是一般的想法

    【讨论】:

      【解决方案2】:

      必须将画布对象的交互回调重新绑定/连接到图形轴对象

      canvas.mpl_connect('button_press_event', view.axes._button_press)
      canvas.mpl_connect('button_release_event', view.axes._button_release)
      canvas.mpl_connect('motion_notify_event', view.axes._on_move)
      

      正如本例中所做的那样:

      https://github.com/precise-simulation/mesh-viewer/blob/master/meshviewer_mpl_tk.py#L296-L298

      【讨论】:

        猜你喜欢
        • 2019-10-07
        • 1970-01-01
        • 2012-07-30
        • 2013-04-17
        • 2015-02-17
        • 1970-01-01
        • 1970-01-01
        • 2011-04-03
        • 2017-08-24
        相关资源
        最近更新 更多