欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

matplotlib.backends.backend_qt5agg.FigureCanvasQTagg构成及用法

程序员文章站 2022-05-28 12:36:35
...
  • 分解

matplotlib:一个绘图用的Python模块

backends:matplotlib中的一个模块,后端。

backend_qt5agg:backends里面的一个模块,里面有两个类:FigureCanvasQTAgg_BackendQT5Agg

FigureCanvasQTagg:backend_qt5agg里的一个类

  • FigureCanvasQTagg应用

matplotlib绘制的图可以应用在PyQt5应用里面,下面三个import都需要:

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

**matplotlib.backends.backend_qt5agg用来连接Matplotlib和PyQt5。**backend_qt5agg.py的原文如下:

"""
Render to qt from agg.
"""

import ctypes

from matplotlib.transforms import Bbox

from .. import cbook
from .backend_agg import FigureCanvasAgg
from .backend_qt5 import (
    QtCore, QtGui, QtWidgets, _BackendQT5, FigureCanvasQT, FigureManagerQT,
    NavigationToolbar2QT, backend_version)
from .qt_compat import QT_API


class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT):

    def __init__(self, figure):
        # Must pass 'figure' as kwarg to Qt base class.
        super().__init__(figure=figure)

    def paintEvent(self, event):
        """Copy the image from the Agg canvas to the qt.drawable.
        In Qt, all drawing should be done inside of here when a widget is
        shown onscreen.
        """
        if self._update_dpi():
            # The dpi update triggered its own paintEvent.
            return
        self._draw_idle()  # Only does something if a draw is pending.

        # If the canvas does not have a renderer, then give up and wait for
        # FigureCanvasAgg.draw(self) to be called.
        if not hasattr(self, 'renderer'):
            return

        painter = QtGui.QPainter(self)

        rect = event.rect()
        left = rect.left()
        top = rect.top()
        width = rect.width()
        height = rect.height()
        # See documentation of QRect: bottom() and right() are off by 1, so use
        # left() + width() and top() + height().
        bbox = Bbox(
            [[left, self.renderer.height - (top + height * self._dpi_ratio)],
             [left + width * self._dpi_ratio, self.renderer.height - top]])
        reg = self.copy_from_bbox(bbox)
        buf = cbook._unmultiplied_rgba8888_to_premultiplied_argb32(
            memoryview(reg))

        # clear the widget canvas
        painter.eraseRect(rect)

        qimage = QtGui.QImage(buf, buf.shape[1], buf.shape[0],
                              QtGui.QImage.Format_ARGB32_Premultiplied)
        if hasattr(qimage, 'setDevicePixelRatio'):
            # Not available on Qt4 or some older Qt5.
            qimage.setDevicePixelRatio(self._dpi_ratio)
        origin = QtCore.QPoint(left, top)
        painter.drawImage(origin / self._dpi_ratio, qimage)
        # Adjust the buf reference count to work around a memory
        # leak bug in QImage under PySide on Python 3.
        if QT_API in ('PySide', 'PySide2'):
            ctypes.c_long.from_address(id(buf)).value = 1

        self._draw_rect_callback(painter)

        painter.end()

    def blit(self, bbox=None):
        """Blit the region in bbox.
        """
        # If bbox is None, blit the entire canvas. Otherwise
        # blit only the area defined by the bbox.
        if bbox is None and self.figure:
            bbox = self.figure.bbox

        # repaint uses logical pixels, not physical pixels like the renderer.
        l, b, w, h = [pt / self._dpi_ratio for pt in bbox.bounds]
        t = b + h
        self.repaint(l, self.renderer.height / self._dpi_ratio - t, w, h)

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


@_BackendQT5.export
class _BackendQT5Agg(_BackendQT5):
    FigureCanvas = FigureCanvasQTAgg
  • Reference

  1. matplotlib.backends.backend_qt5agg
  2. matplotlib/lib/matplotlib/backends/backend_qt5agg.py