Embed an interactive 3D plot in PySide
Question: What is the best way to embed an interactive 3D plot in a PySide GUI? I have
looked at some examples on here of 2D plots embedded in a PySide GUI:

[Getting PySide to Work With
Matplotlib](http://stackoverflow.com/questions/6723527/getting-pyside-to-work-
with-matplotlib)  
[Matplotlib Interactive Graph Embedded In
PyQt](http://stackoverflow.com/questions/16188037/matplotlib-interactive-
graph-embedded-in-pyqt)  
[Python/Matplotlib/Pyside Fast Timetrace
Scrolling](http://stackoverflow.com/questions/16824718/python-matplotlib-
pyside-fast-timetrace-scrolling/16825869#16825869)

However, the functionality that I'm looking for is not quite the same. The
figure needs to rotate and zoom based on mouse input from the user in the same
way as if it were drawn in a separate window.

I'm trying to avoid having to go in manually and write functions for
transforming mouse click + move into a figure rotate and canvas repaint--even
if that's the only way, I'm not even sure how to do that. But I figure (no pun
intended) that there should be a way to reuse the functionality already
present for creating 3D plots in their own windows.

Here's my code. It works as intended, but the plot is not interactive. Any
advice is appreciated!

**EDIT:** I fixed the use of FigureCanvas according to
[tcaswell](http://stackoverflow.com/users/380231/tcaswell)'s corrections. I
also added a bit from the matplotlib [Event Handling and
Picking](http://matplotlib.org/users/event_handling.html) documentation to
show that the figure seems to be getting the events upon mouseclick.

**Final Edit:** The following code now produces the plot as desired.

    
    
    # -*- coding: utf-8 -*-
    
    from PySide import QtCore, QtGui
    import numpy as np
    
    import matplotlib
    import sys
    # specify the use of PySide
    matplotlib.rcParams['backend.qt4'] = "PySide"
    
    # import the figure canvas for interfacing with the backend
    from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg \
                                                                    as FigureCanvas
    
    # import 3D plotting
    from mpl_toolkits.mplot3d import Axes3D    # @UnusedImport
    from matplotlib.figure import Figure
    
    
    # Auto-generated code from QT Designer ----------------------------------------
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(750, 497)
            self.centralwidget = QtGui.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.horizontalLayout_2 = QtGui.QHBoxLayout(self.centralwidget)
            self.horizontalLayout_2.setObjectName("horizontalLayout_2")
            self.frame_2 = QtGui.QFrame(self.centralwidget)
            self.frame_2.setFrameShape(QtGui.QFrame.StyledPanel)
            self.frame_2.setFrameShadow(QtGui.QFrame.Raised)
            self.frame_2.setObjectName("frame_2")
            self.verticalLayout = QtGui.QVBoxLayout(self.frame_2)
            self.verticalLayout.setObjectName("verticalLayout")
            self.label = QtGui.QLabel(self.frame_2)
            self.label.setObjectName("label")
            self.verticalLayout.addWidget(self.label)
            self.label_2 = QtGui.QLabel(self.frame_2)
            self.label_2.setObjectName("label_2")
            self.verticalLayout.addWidget(self.label_2)
            self.lineEdit = QtGui.QLineEdit(self.frame_2)
            sizePolicy = QtGui.QSizePolicy(
                                QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(
                                    self.lineEdit.sizePolicy().hasHeightForWidth())
            self.lineEdit.setSizePolicy(sizePolicy)
            self.lineEdit.setObjectName("lineEdit")
            self.verticalLayout.addWidget(self.lineEdit)
            spacerItem = QtGui.QSpacerItem(
                    20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
            self.verticalLayout.addItem(spacerItem)
            self.horizontalLayout_2.addWidget(self.frame_2)
            self.frame_plot = QtGui.QFrame(self.centralwidget)
            self.frame_plot.setMinimumSize(QtCore.QSize(500, 0))
            self.frame_plot.setFrameShape(QtGui.QFrame.StyledPanel)
            self.frame_plot.setFrameShadow(QtGui.QFrame.Raised)
            self.frame_plot.setObjectName("frame_plot")
            self.horizontalLayout_2.addWidget(self.frame_plot)
            MainWindow.setCentralWidget(self.centralwidget)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            MainWindow.setWindowTitle(QtGui.QApplication.translate(
                "MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
            self.label.setText(QtGui.QApplication.translate("MainWindow",
                        "This is a qlabel.", None, QtGui.QApplication.UnicodeUTF8))
            self.label_2.setText(QtGui.QApplication.translate("MainWindow",
                "And this is another one.", None, QtGui.QApplication.UnicodeUTF8))
            self.lineEdit.setText(QtGui.QApplication.translate("MainWindow",
                        "Text goes here.", None, QtGui.QApplication.UnicodeUTF8))
    
    # Auto-generated code from QT Designer ----------------------------------------
    
    class MainWindow(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
            # intialize the window
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
    
            # create the matplotlib widget and put it in the frame on the right
            self.ui.plotWidget = Mpwidget(parent=self.ui.frame_plot)
    
    class Mpwidget(FigureCanvas):
        def __init__(self, parent=None):
    
            self.figure = Figure(facecolor=(0, 0, 0))
            super(Mpwidget, self).__init__(self.figure)
            self.setParent(parent)
    
            # plot random 3D data
            self.axes = self.figure.add_subplot(111, projection='3d')
            self.data = np.random.random((3, 100))
            self.axes.plot(self.data[0, :], self.data[1, :], self.data[2, :])
    
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        mw = MainWindow()
        mw.show()
    
        # adjust the frame size so that it fits right after the window is shown
        s = mw.ui.frame_plot.size()
        mw.ui.plotWidget.setGeometry(1, 1, s.width() - 2, s.height() - 2)
    
        sys.exit(app.exec_())
    


Answer: You are not using `FigureCanvas` right:

    
    
    class Mpwidget(FigureCanvas):
        def __init__(self, parent=None):
            self.figure = Figure(facecolor=(0, 0, 0))
            super(Mpwidget, self).__init__(self.figure) # this object _is_ your canvas
            self.setParent(parent)
    
            # plot random 3D data
            self.axes = self.figure.add_subplot(111, projection='3d')
            self.data = np.random.random((3, 100))
            self.axes.plot(self.data[0, :], self.data[1, :], self.data[2, :])
    
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        mw = MainWindow()
        mw.show()
    
        # adjust the frame size so that it fits right after the window is shown
        s = mw.ui.frame_plot.size()
        mw.ui.plotWidget.setGeometry(1, 1, s.width() - 2, s.height() - 2)
    
        sys.exit(app.exec_())
    

Every time you called `FigureCanvas(..)` you were attaching the figure to a
new canvas (which were not the `FigureCanvas` you were seeing) hence the call-
backs were never firing (because they were listening on a `FigureCanvas` that
you couldn't see).

