QGraphicsView displays matplotlib drawing refresh pictures

QGraphicsView displays the histogram drawn by matplotlib

 

1. Introduction to each part of Figure

 

The matplotlib official website has an introduction to each part of Figure

https://matplotlib.org/faq/usage_faq.html#what-is-a-backend

Figure is drawing paper, save all axes, artists and canvas. A figure can have one or more axes.

Figure

The whole figure. The figure keeps track of all the child Axes, a smattering of ‘special’ artists (titles, figure legends, etc), and the canvas. (Don’t worry too much about the canvas, it is crucial as it is the object that actually does the drawing to get you your plot, but as the user it is more-or-less invisible to you). A figure can have any number of Axes, but to be useful should have at least one.

The easiest way to create a new figure is with pyplot:

fig = plt.figure()  # an empty figure with no axes
fig, ax_lst = plt.subplots(2, 2)  # a figure with a 2x2 grid of Axes

Axes is the drawing axis, which is a designated area on the figure. A figure can have multiple axes, but an axis can only belong to one figure.

An axes contains 2 (2D) or 3 (3D) axes, which limits the size of the picture.

Each axes has a title and X-axis coordinate x-label, Y-axis coordinate y-label

Axes

This is what you think of as ‘a plot’, it is the region of the image with the data space (marked as the inner blue box). A given figure can contain many Axes, but a given Axes object can only be in one Figure. The Axes contains two (or three in the case of 3D) Axis objects (be aware of the difference between Axes and Axis) which take care of the data limits (the data limits can also be controlled via set via the set_xlim() and set_ylim() Axes methods). Each Axes has a title (set via set_title()), an x-label (set via set_xlabel()), and a y-label set via set_ylabel()).

The Axes class and it’s member functions are the primary entry point to working with the OO interface.

axis is the coordinate axis, set the coordinate scale. The position of the scale is determined byLocator决定,刻度显示格式由Formatter决定。

Axis

These are the number-line-like objects (circled in green). They take care of setting the graph limits and generating the ticks (the marks on the axis) and ticklabels (strings labeling the ticks). The location of the ticks is determined by a Locator object and the ticklabel strings are formatted by a Formatter. The combination of the correct Locator and Formatter gives very fine control over the tick locations and labels.

Essentially everything that can be seen on the figure, including axes, axes, lines, and text, is an artist. After the figure is rendered, all the artists are drawn on the canvas. Most artists belong to a certain axis.

Artist

Basically everything you can see on the figure is an artist (even the FigureAxes, and Axis objects). This includes Text objects, Line2D objects, collection objects, Patch objects ... (you get the idea). When the figure is rendered, all of the artists are drawn to the canvas. Most Artists are tied to an Axes; such an Artist cannot be shared by multiple Axes, or moved from one to another.

 

Two, QGraphicsView displays the histogram drawn by matplotlib

After setting up the interface using QtDesigner, there is an interface that needs to display a histogram. Checked Pyqt5 can draw histogram through matplotlib. Refer to the following document to draw.

https://www.cnblogs.com/laoniubile/p/5904817.html

The introduction of Figure, axis and axes is as follows:

https://matplotlib.org/api/_as_gen/matplotlib.figure.Figure.html

https://matplotlib.org/api/axis_api.html

https://matplotlib.org/api/axes_api.html

https://matplotlib.org/api/artist_api.html

The first step is to connect to PyQt5 through the matplotlib.backends.backend_qt5agg class, which involves the concept of backend

Backend official website introduction: https://matplotlib.org/faq/usage_faq.html#what-is-a-backend

Matplotlib is often used in python shell for interactive programming. It is also used as a graphical interface like wxpython and pygtk, and it is also used in web application servers to dynamically provide pictures. Therefore, in order to be able to cover all these requirements, matplotlib provides a back end pointing to different outputs, and the corresponding front end is the code interface written and used by the user. There are two types of backends, one is user interface backends (used for interactive backends such as pygtk, wxpython, tkinter, qt4, or macosx), and the other is hardcopy backends (mainly used for PNG, SVG, PDF) , PS such pictures are rendered and saved).


 

import matplotlib
matplotlib.use("Qt5Agg")
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
from matplotlib import pyplot

pyplot.rcParams['font.sans-serif'] = ['SimHei']
pyplot.rcParams['axes.unicode_minus'] = False

Step 2: Implementation of specific graphics code. The key is to refresh the canvas with self.fig.canvas.draw() after each drawing. There is no such sentence at the beginning, only the first picture can be displayed. After redrawing the picture with axes later, the display will no longer refresh. In order to find the cause of the problem, save the redrawn picture with self.fig.savefig(filename) to see if it is the reason for the drawing or the display. It turns out that after adding savefig, the display is also normal, and the saved pictures are also normal.

What operation did savefig do to refresh the display? In the figure source file, you can see that self.canvas.print_figure(fname, **kwargs) was executed.

Why can it be refreshed after executing this step? In order to find the source code of print_figure, an error parameter was passed to make the execution of print_figure fail.

Finally found the print_figure method defined in backend_qt5agg.py, and there is a draw() method for canvas refresh.

class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT):


    def print_figure(self, *args, **kwargs):
        super().print_figure(*args, **kwargs)
        self.draw()

 

class Figure_Bar(FigureCanvasQTAgg):

    def __init__(self, width ,height , parent = None):

        self.fig = pyplot.figure(figsize=(width, height), facecolor='#666666', dpi= 100, edgecolor='#0000FF')
        FigureCanvasQTAgg.__init__(self, self.fig )
        self.setParent(parent)

        self.myAxes = self.fig.add_subplot(111)

        self.x = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 ]

    def ShowImage(self, axisX, axisY ):
        filename = os.getcwd() + "/" + datetime.datetime.now().strftime('%H-%M-%S.%f') + ".png"

        #由于图片需要反复绘制,所以每次绘制前清空,然后绘图,最后刷新显示。
        self.myAxes.clear()
      
        self.myAxes.bar(self.x, axisY, width = 0.02, color = 'blue', align = 'center', tick_label =  axisX )

        # 刷新画布,否则不刷新显示
        self.fig.canvas.draw()  

The third step is to present the graphics drawn by matplotlib through the QGraphicsView control on the GUI

        #获取graphicsView的长和宽单位为像素,Figure的单位是inches,在DPI为100时,除以100转换为inches
        width = self.graphicsView.width()
        height = self.graphicsView.height()

        self.myImage = Figure_Bar(width/100, height/100)

      
        self.myGraphyScene = QGraphicsScene()
        #取消水平和垂直滚动条
        self.graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 
        self.graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.myQGraphicsProxyWidget = self.myGraphyScene.addWidget(self.myImage)
        self.graphicsView.setScene(self.myGraphyScene)

        #每次显示不同图像,只需调用ShowImage方法
        self.myImage.ShowImage(self.axisXcontent, self.axisYcontent)

Guess you like

Origin blog.csdn.net/bluewhu/article/details/104937341