仅在面板调整大小事件结束时重新绘制图形
Replot figure only at the end of a panel resize event
我目前正在尝试改进软件的绘图部分。
我们正在使用 WXPython 和 Matplotlib 来向用户展示许多图表以及对它们的各种控制。
综上所述,上下文如下:
Matplotlib 的性能可以满足我们的绘图需求,但是,调整我们的 wxpython 主框架的大小正在调整包含 matplotlib 的 wx 面板的大小 canvas。
(在每一步或调整大小时,不仅在最后)
快速调整面板大小,但 matplotlib 也在重新绘制 canvas 和调整大小的每个步骤中的图形,造成视觉冻结和一些滞后。
综上所述,问题:
我想知道是否有办法在我们的 WX 帧调整大小事件期间禁用(临时)matplotlib events/auto-redrawing 东西,然后在它结束时应用重绘。
有什么想法吗?
这只是答案的一半,因为 (1) 我在这里使用 PyQt 而不是 WX,并且 (2) 它只展示了如何防止调整大小发生,以便以后可以手动完成。
想法是继承 FigureCanvas
并接管 resizeEvent
方法。在此方法中仅存储调整大小事件,但不要让它发生。
稍后手动触发事件。
import sys
from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np
class MyFigureCanvas(FigureCanvas):
""" Subclass canvas to catch the resize event """
def __init__(self, figure):
self.lastEvent = False # store the last resize event's size here
FigureCanvas.__init__(self, figure)
def resizeEvent(self, event):
if not self.lastEvent:
# at the start of the app, allow resizing to happen.
super(MyFigureCanvas, self).resizeEvent(event)
# store the event size for later use
self.lastEvent = (event.size().width(),event.size().height())
print "try to resize, I don't let you."
def do_resize_now(self):
# recall last resize event's size
newsize = QtCore.QSize(self.lastEvent[0],self.lastEvent[1] )
# create new event from the stored size
event = QtGui.QResizeEvent(newsize, QtCore.QSize(1, 1))
print "Now I let you resize."
# and propagate the event to let the canvas resize.
super(MyFigureCanvas, self).resizeEvent(event)
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.main_widget = QtGui.QWidget(self)
l = QtGui.QVBoxLayout(self.main_widget)
self.fig = Figure()
# use subclassed FigureCanvas
self.canvas = MyFigureCanvas(self.fig)
self.button = QtGui.QPushButton("Manually Resize")
l.addWidget(self.button)
l.addWidget(self.canvas)
self.setCentralWidget(self.main_widget)
self.button.clicked.connect(self.action)
self.plot()
def action(self):
# when button is clicked, resize the canvas.
self.canvas.do_resize_now()
def plot(self):
# just some random plots
self.axes = []
for i in range(4):
ax = self.fig.add_subplot(2,2,i+1)
a = np.random.rand(100,100)
ax.imshow(a)
self.axes.append(ax)
self.fig.tight_layout()
qApp = QtGui.QApplication(sys.argv)
aw = ApplicationWindow()
aw.show()
sys.exit(qApp.exec_())
可能在 WX 中执行此操作并没有太大区别。
我目前正在尝试改进软件的绘图部分。
我们正在使用 WXPython 和 Matplotlib 来向用户展示许多图表以及对它们的各种控制。
综上所述,上下文如下:
Matplotlib 的性能可以满足我们的绘图需求,但是,调整我们的 wxpython 主框架的大小正在调整包含 matplotlib 的 wx 面板的大小 canvas。
(在每一步或调整大小时,不仅在最后)
快速调整面板大小,但 matplotlib 也在重新绘制 canvas 和调整大小的每个步骤中的图形,造成视觉冻结和一些滞后。
综上所述,问题:
我想知道是否有办法在我们的 WX 帧调整大小事件期间禁用(临时)matplotlib events/auto-redrawing 东西,然后在它结束时应用重绘。
有什么想法吗?
这只是答案的一半,因为 (1) 我在这里使用 PyQt 而不是 WX,并且 (2) 它只展示了如何防止调整大小发生,以便以后可以手动完成。
想法是继承 FigureCanvas
并接管 resizeEvent
方法。在此方法中仅存储调整大小事件,但不要让它发生。
稍后手动触发事件。
import sys
from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np
class MyFigureCanvas(FigureCanvas):
""" Subclass canvas to catch the resize event """
def __init__(self, figure):
self.lastEvent = False # store the last resize event's size here
FigureCanvas.__init__(self, figure)
def resizeEvent(self, event):
if not self.lastEvent:
# at the start of the app, allow resizing to happen.
super(MyFigureCanvas, self).resizeEvent(event)
# store the event size for later use
self.lastEvent = (event.size().width(),event.size().height())
print "try to resize, I don't let you."
def do_resize_now(self):
# recall last resize event's size
newsize = QtCore.QSize(self.lastEvent[0],self.lastEvent[1] )
# create new event from the stored size
event = QtGui.QResizeEvent(newsize, QtCore.QSize(1, 1))
print "Now I let you resize."
# and propagate the event to let the canvas resize.
super(MyFigureCanvas, self).resizeEvent(event)
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.main_widget = QtGui.QWidget(self)
l = QtGui.QVBoxLayout(self.main_widget)
self.fig = Figure()
# use subclassed FigureCanvas
self.canvas = MyFigureCanvas(self.fig)
self.button = QtGui.QPushButton("Manually Resize")
l.addWidget(self.button)
l.addWidget(self.canvas)
self.setCentralWidget(self.main_widget)
self.button.clicked.connect(self.action)
self.plot()
def action(self):
# when button is clicked, resize the canvas.
self.canvas.do_resize_now()
def plot(self):
# just some random plots
self.axes = []
for i in range(4):
ax = self.fig.add_subplot(2,2,i+1)
a = np.random.rand(100,100)
ax.imshow(a)
self.axes.append(ax)
self.fig.tight_layout()
qApp = QtGui.QApplication(sys.argv)
aw = ApplicationWindow()
aw.show()
sys.exit(qApp.exec_())
可能在 WX 中执行此操作并没有太大区别。