SirIguan SirIguan - 6 months ago 116
Python Question

How to plot different graphs in different canvas in PyQt4 in a window?

I am trying to code with python3 a GUI that plots 4 different graph in 4 respective layout : speed, height, coordinates and the angle. Right now I am able to draw the figure in each respective layout. However, I have no idea how to plot different function into each graph. I used a method to randomly generate 10 points to plot. When the method is called, it plots the same graph into each 4 canvas.

So my question is **if there is anyway to plot different function respectively to a figure(one plot per graph)?**I am pretty new to python3 and would be grateful for any help provided.

If possible, I would like to avoid using many subplots in a figure since a layout for each figures exist already.

Here is what the current GUI looks like when I call the test method that generates random points, you can see that
the same graph are plotted in each canvas

I will also mention, if it adds any constraints, that this code will eventually be used to plots graph that will update with data coming from another thread.

And here's the code:

from PyQt4 import QtGui
from .flight_dataUI import Ui_Dialog
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
import random

class FlightData(QtGui.QDialog, Ui_Dialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)

self.figure = plt.figure() # FlightData.figure = matplotlib.pyplot.figure()
# Creates a figure widget self.name = FigureCanvas(self.figure)
self.speedGraph = FigureCanvas(self.figure)
self.heightGraph = FigureCanvas(self.figure)
self.mapGraph = FigureCanvas(self.figure)
self.angleGraph = FigureCanvas(self.figure)
# -------------------------------------------------------------
self.speedLayout.addWidget(self.speedGraph) # insert widget "speedGraph" in speedLayout
self.heightLayout.addWidget(self.heightGraph) # insert widget "heightGraph" in heightLayout
self.mapLayout.addWidget(self.mapGraph) # insert widget "mapGraph" in mapLayout
self.angleLayout.addWidget(self.angleGraph) # insert widget "angleGraph" in angleLayout
self.ax = self.figure.add_subplot(111)
self.ax.hold(False)

self.init_widgets()

def init_widgets(self):
self.analyseButton.clicked.connect(self.open_analysedata)
self.draw_plot()

def open_analysedata(self):
self.done(2) # Closes and delete Dialog window et and return the int 2 as a results in main_window.py

def draw_plot(self):
data = [random.random() for i in range(10)]
self.ax.plot(data, '-*')

Answer

If embedding do not import pyplot, it's global state will only cause you trouble. You are using the same figure to initialize all 4 FigureCanvas objects. You want to do something like:

from matplotlib.figure import Figure

class FlightData(QtGui.QDialog, Ui_Dialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.setupUi(self)
        self.figs = {}
        self.canvas = {}
        self.axs = {}
        plot_names = ['speed', 'height', 'map', 'angle']
        for pn in plot_names:
            fig = Figure()
            self.canvas[pn] = FigureCanvas(fig)
            ax = fig.add_subplot(1, 1, 1)

            self.figs[pn] = fig
            self.axs[pn] = ax

        # -------------------------------------------------------------
        self.speedLayout.addWidget(self.canvas['speed'])
        self.heightLayout.addWidget(self.canvas['height'])
        self.mapLayout.addWidget(self.canvas['map'])
        self.angleLayout.addWidget(self.canvas['angle'])

    def draw_plot(self, target, data):
        self.axs[target].plot(data, '-*')
        self.canvas[target].draw_idle()
Comments