Python – Interacting with MatplotlibWidget created with Qt Designer in python code

matplotlibpyqtpythonpython-embedding

I am facing a problem interacting with the MatplotlibWidget that I creater via Qt Designer. I am unable to change the axes labels, scale, provide titles or anything. Am i doing anything wrong?

This is a sample UI code generated using Qt Designer:

from PyQt4 import QtCore, QtGui

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.mplwidget = MatplotlibWidget(self.centralwidget)

        self.mplwidget.setGeometry(QtCore.QRect(70, 50, 400, 300))
        self.mplwidget.setObjectName("mplwidget")

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))

from matplotlibwidget import MatplotlibWidget

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()):
        QtGui.QMainWindow.__init__(self, parent, f)

        self.setupUi(self)

This is the python code i wrote to interact with the UI python Code:

from PyQt4 import QtGui, QtCore
from TestUI2 import MainWindow

class Window(MainWindow):
    def __init__(self):
        MainWindow.__init__(self)

        x=[0,10,100]
        y=[3,4,5]

        self.mplwidget.axes.set_xscale('log') # Nothing Happens 
        self.mplwidget.axes.set_title('GRAPH') # Nothing Happens

        self.mplwidget.axes.plot(x,y) 


if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

Best Answer

You need to define your own class for MatplotlibWidget first (in your main script, not the UI code) and then instantialize it in Window() definintion. To do that you also need to import FigureCanvas from _qt4agg matplotlib backend module and Figure class:

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure

Then in the Matplotlib class definition you create instances of the Figure subplots and Figure canvas, that can then be used to interact with your plot from the main window. So using your code this would look like this:

from PyQt4 import QtGui, QtCore
from TestUI2 import MainWindow

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure

class Window(MainWindow):
    def __init__(self):
        MainWindow.__init__(self)

        x=[0,10,100]
        y=[3,4,5]

        self.mplwidget = MatplotlibWidget(self.centralwidget)

        self.mplwidget.setGeometry(QtCore.QRect(70, 50, 600, 500))
        self.mplwidget.setObjectName("mplwidget")

        self.mplwidget.plotDataPoints(x,y)    

class MatplotlibWidget(Canvas):        
    def __init__(self, parent=None, title='Title', xlabel='x label', ylabel='y label', dpi=100, hold=False):
        super(MatplotlibWidget, self).__init__(Figure())

        self.setParent(parent)
        self.figure = Figure(dpi=dpi)
        self.canvas = Canvas(self.figure)
        self.theplot = self.figure.add_subplot(111)        

        self.theplot.set_title(title)
        self.theplot.set_xlabel(xlabel)
        self.theplot.set_ylabel(ylabel)

    def plotDataPoints(self, x, y):
        self.theplot.plot(x,y)
        self.draw()            

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

And the Ui script:

from PyQt4 import QtCore, QtGui

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)

        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")        

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)       

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()):
        QtGui.QMainWindow.__init__(self, parent, f)

        self.setupUi(self)

And then if you want to interact with the mpl plot, for example to change a title you do it from within the Window class, say:

self.mplwidget.theplot.set_title("New Title")

Hope that helps.