SoFunction
Updated on 2024-11-17

Implementation of Plotting with Matplotlib Embedded in Pyside2

Recently encountered a need, is to use PySide2 to make a GUI, and to use Matplotlib in the background to draw the figure displayed on the interface. I've been thinking about it for a long time, and I've searched the Internet for a lot of information, but it all feels mixed, so I'll summarize it myself.

We use the QGraphicsView plugin to display images drawn in Matplotlib. The function demonstrated here is: the interface defaults to drawing the image of the cos function when opened, and draws the image of the sin function when the button is clicked.

1. Interface design

Simply create an interface: a GraphicsView and a PushButton.

2. Define a class that inherits FigureCanvas.

import matplotlib
from .backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
# from  import Figure
import  as plt
 
("Qt5Agg") # Declare the use of QT5
 
 
class MyFigureCanvas(FigureCanvas):
  '''
  By inheriting the FigureCanvas class, the class is made to be both a PyQt5 Qwidget and a matplotlib FigureCanvas, which is the key to connecting pyqt5 to matplotlib
  '''
  def __init__(self, parent=None, width=10, height=5, xlim=(0, 2500), ylim=(-2, 2), dpi=100):
    # Create a Figure
    fig = (figsize=(width, height), dpi=dpi, tight_layout=True) # tight_layout: used to remove white space on both sides of the drawing
 
    FigureCanvas.__init__(self, fig) # Initialize the parent class
    (parent)
 
     = fig.add_subplot(111) # Add subgraphs
    ['top'].set_visible(False) # Remove the horizontal line above the drawing
    ['right'].set_visible(False) # Remove the horizontal line on the right side of the drawing
    .set_xlim(xlim)
    .set_ylim(ylim)

Then you can start plotting.

3. Plotting and display

3.1 Initialize the class we defined first

Here () / 101 works:

  • Because the size of the drawing drawn directly using the default drawing is usually not the same as the size of the GraphicsView in our window, it will cause the image to be displayed incompletely and you need to drag the scroll bar to see the image. Here we set the size of the drawing to match the size of the GraphicsView, and it will show the full image. The reason for the "/101", I feel, may be that the result of () is not in the same unit as the parameter that sets the plot size in plt's figsize, so it has to be divided by a number so that the image can be displayed just in full in the GraphicsView.
# Initialize the display of gv_visual_data
self.gv_visual_data_content = MyFigureCanvas(width=() / 101,
                       height=() / 101,
                       xlim=(0, 2*),
                       ylim=(-1, 1)) # Instantiate aFigureCanvas

3.2 Matplotlib is then used to plot the image of the cos function and display it in the GraphicsView.

x = (0, 2 * ,  / 100)
y = (x)
self.gv_visual_data_content.(x, y)
self.gv_visual_data_content.axes.set_title('cos()')
# The loaded graphics (FigureCanvas) cannot be put directly into the graphicview control, it must be put into the graphicScene first, and then the graphicscene into the graphicview.
self.graphic_scene = QGraphicsScene() # Create a QGraphicsScene
self.graphic_scene.addWidget(self.gv_visual_data_content) # Put the graphic into the QGraphicsScene, note: the graphic is put into the QGraphicsScene as a QWidget
(self.graphic_scene) # Putting a QGraphicsScene into a QGraphicsView
() # invocationsshowMethods to present graphs

By this point, you can already run and see the initial results

3.3 Next, implement the function that switches to the image of the sin function at the click of a button

Connect the signal to the slot first

.btn_sin.(self.plot_sin)

Writing Slot Functions

  def plot_sin(self):
    x = (0, 2 * ,  / 100)
    y = (x)
    self.gv_visual_data_content.() # Since the image needs to be drawn repeatedly, clear it before each drawing and then draw it
    self.gv_visual_data_content.(x, y)
    self.gv_visual_data_content.axes.set_title('sin()')
    self.gv_visual_data_content.draw() # Refresh the canvas to display the image,Otherwise the display is not refreshed

All right, let's see how it works.

Great job.

Full Code:

Attention:When importing packages, put the PySide2 and UI packages in the matplotlib-related packages in theaheadOtherwise, the inside self.graphic_scene.addWidget(self.gv_visual_data_content) will report the following error here!

TypeError: '' called with wrong argument types:
  (MyFigureCanvas)
Supported signatures:
  (, = Default())

As for why? I'm not quite sure, but it seems that if you're using PyQt5 you don't have this problem, metaphysics!!!!

from  import QApplication, QMainWindow, QGraphicsScene, QFileDialog, QMessageBox
from  import Ui_MainWindow
 
import sys
import numpy as np
import matplotlib
from .backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
# from  import Figure
import  as plt
 
("Qt5Agg") # Declare the use of QT5
 
 
class MyFigureCanvas(FigureCanvas):
  '''
  By inheriting the FigureCanvas class, the class is made to be both a PyQt5 Qwidget and a matplotlib FigureCanvas, which is the key to connecting pyqt5 to matplotlib
  '''
  def __init__(self, parent=None, width=10, height=5, xlim=(0, 2500), ylim=(-2, 2), dpi=100):
    # Create a Figure
    fig = (figsize=(width, height), dpi=dpi, tight_layout=True) # tight_layout: used to remove white space on both sides of the drawing
 
    FigureCanvas.__init__(self, fig) # Initialize the parent class
    (parent)
 
     = fig.add_subplot(111) # Call the add_subplot method under figure, similar to the following subplot method
    ['top'].set_visible(False) # Remove the horizontal line above
    ['right'].set_visible(False)
    .set_xlim(xlim)
    .set_ylim(ylim)
 
class MainWindow(QMainWindow):
  def __init__(self):
    super().__init__()
     = Ui_MainWindow()
    (self)
 
    # Initialize the display of gv_visual_data
    self.gv_visual_data_content = MyFigureCanvas(width=() / 101,
                           height=() / 101,
                           xlim=(0, 2*),
                           ylim=(-1, 1)) # Instantiate a FigureCanvas
    self.plot_cos()
 
    .btn_sin.(self.plot_sin)
 
  def plot_cos(self):
    x = (0, 2 * ,  / 100)
    y = (x)
    self.gv_visual_data_content.(x, y)
    self.gv_visual_data_content.axes.set_title('cos()')
    # The loaded graphics (FigureCanvas) cannot be put directly into the graphicview control, it must be put into the graphicScene first, and then the graphicscene into the graphicview.
    self.graphic_scene = QGraphicsScene() # Create a QGraphicsScene
    self.graphic_scene.addWidget(self.gv_visual_data_content) # Put the graphic into the QGraphicsScene, note: the graphic is put into the QGraphicsScene as a QWidget
    (self.graphic_scene) # Putting a QGraphicsScene into a QGraphicsView
    () # Call the show method to render a graphic
 
  def plot_sin(self):
    x = (0, 2 * ,  / 100)
    y = (x)
    self.gv_visual_data_content.() # Since the image needs to be drawn repeatedly, clear it before each drawing and then draw it
    self.gv_visual_data_content.(x, y)
    self.gv_visual_data_content.axes.set_title('sin()')
    self.gv_visual_data_content.draw() # Refresh the canvas to display the image, otherwise do not refresh the display
 
 
if __name__ == "__main__":
  app = QApplication()
  win = MainWindow()
  ()
  (app.exec_())

to this article on Pyside2 embedded Matplotlib plotting implementation of the article is introduced to this, more related Pyside2 embedded Matplotlib content, please search for my previous posts or continue to browse the following related articles I hope you will support me in the future!