Search code examples
pythonmatplotlibwxpython

How to use mouse to rotate matplotlib 3D plots in wxPython?


Here is a snippet of code I use to display a 2D matplotlib plot in a wxPython application:

import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure
import wx

[wxPython application and class code snipped]

    figure = Figure()
    axes = figure.add_subplot(111)
    canvas = FigureCanvasWxAgg(self, wx.ID_ANY, figure)
    plotSizer = wx.BoxSizer(wx.VERTICAL)
    plotSizer.Add(self, canvas, proportion=1, flag=wx.EXPAND)
    plotPanel = wx.Panel(self, wx.ID_ANY, size=DEFAULT_PLOT_SIZE)
    plotPanel.SetSizer(plotSizer)

I can plot to the axes, redraw the canvas and pan and zoom. When I try to do the equivalent using 3D, the 3D plot is displayed, but I can't rotate/pan/zoom. The only difference in this code is the additional import for 3D and addition of projection parameter to add_subplot().

import matplotlib
matplotlib.use('WXAgg')
from mpl_toolkits.mplot3d import axes3d
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure
import wx

[wxPython application and class code snipped]

    figure = Figure()
    axes = figure.add_subplot(111, projection="3d")
    canvas = FigureCanvasWxAgg(self, wx.ID_ANY, figure)
    plotSizer = wx.BoxSizer(wx.VERTICAL)
    plotSizer.Add(self, canvas, proportion=1, flag=wx.EXPAND)
    plotPanel = wx.Panel(self, wx.ID_ANY, size=DEFAULT_PLOT_SIZE)
    plotPanel.SetSizer(plotSizer)

I get this warning:

...\site-packages\mpl_toolkits\mplot3d\axes3d.py:1009: UserWarning: Axes3D.figure.canvas is 'None', mouse rotation disabled.  Set canvas then call Axes3D.mouse_init().

So I tried setting Axes3D.figure.canvas with this code after the call to FigureCanvasWxAgg():

axes.figure.canvas = canvas
axes.mouse_init()

But this doesn't work; I still can't use the mouse to rotate the 3D plot.

The demo source code at http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html that uses stand-alone matplotlib work; I can use the mouse to rotate the plots there. How can I get mouse rotation working when using wxPython?


Solution

  • Turns out I just had to swap the order of the canvas and axes creation. The canvas should be created and added to the figure first, then the 3D axes can be created.

    figure = Figure()
    canvas = FigureCanvasWxAgg(self, wx.ID_ANY, figure)
    axes = figure.add_subplot(111, projection="3d")
    plotSizer = wx.BoxSizer(wx.VERTICAL)
    plotSizer.Add(self, canvas, proportion=1, flag=wx.EXPAND)
    plotPanel = wx.Panel(self, wx.ID_ANY, size=DEFAULT_PLOT_SIZE)
    plotPanel.SetSizer(plotSizer)