0

I wanna embed a Matplotlib plot directly into a window, QMainWindow. It should be part of my program with a more complex GUI. ;)

The only way I found was to add the figure as widget into a QTabWidget. See sample code below. I lost the link to the webpage what inspired me.

Is there any way to embed the figure directly into the windows like other elements (buttons, textfield, textarea, ...)?

import sys
from PyQt4.QtGui import QApplication, QMainWindow, QDockWidget, QVBoxLayout,QTabWidget, QWidget
from matplotlib import pyplot
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg

a = QApplication(sys.argv)
w = QMainWindow()
t = QTabWidget(w)
Tab1 = QWidget()
t.addTab(Tab1, '1st Plot')
t.resize(1280, 300)

x = [1, 2, 3]
Fig1 = pyplot.Figure();
Plot =  Fig1.add_subplot(111);
Plot.plot(x)
Plot.grid();

layout = QVBoxLayout();
layout.addWidget(FigureCanvasQTAgg(Fig1));
Tab1.setLayout(layout);

w.showMaximized()
sys.exit(a.exec_())

Thank you very much.

Fabian
  • 51
  • 1
  • 6
  • This question might help -> http://stackoverflow.com/questions/29766341 . It's not exactly a duplicate, but it does add a matplotlib figure to a Qt main window (see my full code for the answer here (http://pastebin.com/gv7Cmapr) in particular __init__ . If that's enough, great. If not, but it looks like what you want, reply to this comment and I'll try to put a full answer together. – J Richard Snape Jan 05 '16 at 21:16

2 Answers2

0

FigureCanvasQtAgg is just a QWidget like any of the other controls you mentioned. The main difference being it doesn't allow you to pass a parent in the constructor like when you write

t = QTabWidget(w)

You can achieve the same with FigureCanvasQtAgg by calling setParent

canvas = FigureCanvasQtAgg(Fig1)
canvas.setParent(w)

You can also use QMainWindow's setCentralWidget method to add the matplotlib FigureCanvas directly to your main window. However, if you want a more complex gui with other controls I don't see any real problems with your current approach.

Lastly, you shouldn't really be using pyplot when embedding matplotlib. Stick with the object oriented API. Take a look at this example.

user3419537
  • 4,740
  • 2
  • 24
  • 42
0

This is what I use for PySide. FigureCanvasQTAgg is a qt widget, so you don't need the PlotWidget class. I just find it useful, because it creates the figure for me. It also makes it useful for other projects, because you don't have to deal with importing the right matplotlib objects. From the PlotWidget just call the axes for all of your plotting needs.

from PySide import QtGui

import matplotlib
matplotlib.use("Qt4Agg")
matplotlib.rcParams["backend.qt4"] = "PySide"

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar

class PlotWidget(FigureCanvas):
    '''Plotting widget that can be embedded in a PySide GUI.'''
    def __init__(self, figure=None):
        if figure is None:
            figure = Figure(tight_layout=True)
        super().__init__(figure)

        self.axes = self.figure.add_subplot(111)

        self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
# end class

if __name__ == "__main__":
    import sys

    a = QtGui.QApplication(sys.argv)

    w = QtGui.QMainWindow()
    w.show()

    p = PlotWidget()
    p.axes.plot([])

    nav = NavigationToolbar(p, w)
    w.addToolBar(nav)

    w.setCentralWidget(p)

    # or
    # container = QtGui.QWidget()
    # layout = QtGui.QHBoxLayout()
    # container.setLayout(layout)
    # w.setCentralWidget(container)
    # layout.addWidget(p)

    sys.exit(a.exec_())
justengel
  • 6,132
  • 4
  • 26
  • 42