Я использую matplotlib backend_qt5agg
для обработки рисования холста matplotlib в окне qt.Пользователь может рисовать прямоугольники (типа matplotlib.patches.Rectangle
) на графике, и я показываю прямоугольник, вызывая метод canvas.draw()
.Этот метод может быть довольно медленным, если холст содержит много данных, и я хотел бы ускорить его.
Поиск решений, которые я нашел в руководстве backend_qt5agg
, о существовании метода, называемого drawRectangle(rect)
.В надежде, что этот метод может нарисовать только патч без перерисовки всего холста, я попытался вызвать этот метод, используя в качестве входных данных патч Rectangle.Поэтому я звоню canvas.drawRectangle(my_rect)
вместо того, чтобы звонить canvas.draw()
.Это ничего не рисует.
К сожалению, руководство backend_qt5agg
чисто документировано.Итак, мой вопрос: как работает метод drawRectangle
и должен ли он работать лучше, чем перерисовка всего холста?
Минимальный пример (прямоугольник отображается при щелчке мыши и перемещении внутри холста) (простоизмените self.canvas.draw()
на self.canvas.drawRectangle(self.rect)
внутри on_motion
, чтобы проверить метод drawRectangle
):
import sys
import matplotlib
from PyQt5 import QtCore
import PyQt5.QtWidgets as QtW
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.patches import Rectangle
class MainWindow(QtW.QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('MyWindow')
self._main = QtW.QWidget()
self.setCentralWidget(self._main)
# Set canvas properties
self.fig = matplotlib.figure.Figure(figsize=(5,5))
self.canvas = FigureCanvasQTAgg(self.fig)
self.ax = self.fig.add_subplot(1,1,1)
self.rect = Rectangle((0,0), 0.2, 0.2, color='k', fill=None, alpha=1)
self.ax.add_patch(self.rect); self.rect.set_visible(False)
self.canvas.draw()
# set Qlayout properties and show window
self.gridLayout = QtW.QGridLayout(self._main)
self.gridLayout.addWidget(self.canvas)
self.setLayout(self.gridLayout)
self.show()
# connect mouse events to canvas
self.fig.canvas.mpl_connect('button_press_event', self.on_click)
self.fig.canvas.mpl_connect('motion_notify_event', self.on_motion)
def on_click(self, event):
if event.button == 1 or event.button == 3:
# left or right click: get the x and y coordinates
if event.inaxes is not None:
self.xclick = event.xdata
self.yclick = event.ydata
self.on_press = True
def on_motion(self, event):
# draw the square
if event.button == 1 or event.button == 3 and self.on_press == True:
if (self.xclick is not None and self.yclick is not None):
x0, y0 = self.xclick, self.yclick
x1, y1 = event.xdata, event.ydata
if (x1 is not None or y1 is not None):
self.rect.set_width(x1 - x0)
self.rect.set_height(y1 - y0)
self.rect.set_xy((x0, y0))
self.rect.set_visible(True)
self.canvas.draw() # self.canvas.drawRectangle(self.rect)
if __name__ == '__main__':
app = QtCore.QCoreApplication.instance()
if app is None: app = QtW.QApplication(sys.argv)
win = MainWindow()
app.aboutToQuit.connect(app.deleteLater)
app.exec_()