Python Tkinter 3d图无法平移或缩放

时间:2019-01-09 23:33:19

标签: python-3.x matplotlib tkinter

我一直在尝试使用TKinter在我的Python GUI应用程序中使用matplotlib包括2d / 3d图,并且在2d图上取得了成功,但在3d图上却没有。我的问题是,即使导航窗格中的按钮已响应按钮单击,也无法平移或缩放3d图。这是演示我的问题的示例代码:

import tkinter as tk

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import numpy as np

root = tk.Tk()
frame = tk.Frame(root)
frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

#uncomment as needed to demonstrate 2d/3d plot
#subplot_kw = {'projection':'3d'}
subplot_kw = {}
fig, ax = plt.subplots(subplot_kw=subplot_kw)
if len(subplot_kw) > 0:
    ax.plot(range(100), np.random.rand(100), np.random.rand(100))
else:
    ax.plot(range(100), np.random.rand(100))

canvas = FigureCanvasTkAgg(fig, frame)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)

toolbar = NavigationToolbar2Tk(canvas, frame)
toolbar.update()

root.mainloop()

因此,当我使用上面的代码绘制2d时,可以平移/缩放工作。当我更改注释的行并使用3D绘图时,平移/缩放不起作用。我是否错过了一些简单的东西,或者使用matplotlib在tkinter中进行3d平移/缩放有问题吗?

1 个答案:

答案 0 :(得分:2)

首先,不要使用pyplot创建要嵌入到tkinter(或任何其他GUI)中的图形,因为由pyplot和自定义GUI管理同一图形可能会导致各种问题。在这种情况下,使用matplotlib.figure.Figure(如the "Embedding in tk" example中所示)将具有发出有关该问题的警告的额外好处:

  

UserWarning: Axes3D.figure.canvas is 'None', mouse rotation disabled. Set canvas then call Axes3D.mouse_init().

从本质上讲,这意味着您需要调用mouse_init(),或者只需在设置画布后 创建3D轴。后者如下所示。

import tkinter
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_tkagg import (
                                    FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure

root = tkinter.Tk()
root.wm_title("Embedding in Tk")

fig = Figure(figsize=(5, 4), dpi=100)

canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.draw()

ax = fig.add_subplot(111, projection="3d")
t = np.arange(0, 3, .01)
ax.plot(t, 2 * np.sin(2 * np.pi * t))

toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)


tkinter.mainloop()