Python 仅在面板调整大小事件结束时重新打印图形
我目前正在尝试改进软件的绘图部分 我们使用WXPython和Matplotlib向用户显示许多带有各种控件的绘图 总而言之,以下是上下文: Matplotlib的性能可以满足打印需要,但是,调整wxpython主框架的大小就是调整包含Matplotlib画布的wx面板的大小 (在每个步骤或调整大小时,而不仅仅是在结束时) 若调整面板的大小很快,matplotlib也会在调整大小的每个步骤中重新绘制画布和图形,造成视觉冻结和一些延迟 总而言之,问题在于: 我想知道是否有办法在WX Frame resize事件期间禁用(临时)matplotlib事件/自动重画内容,然后在其末尾应用重画Python 仅在面板调整大小事件结束时重新打印图形,python,performance,matplotlib,wxpython,Python,Performance,Matplotlib,Wxpython,我目前正在尝试改进软件的绘图部分 我们使用WXPython和Matplotlib向用户显示许多带有各种控件的绘图 总而言之,以下是上下文: Matplotlib的性能可以满足打印需要,但是,调整wxpython主框架的大小就是调整包含Matplotlib画布的wx面板的大小 (在每个步骤或调整大小时,而不仅仅是在结束时) 若调整面板的大小很快,matplotlib也会在调整大小的每个步骤中重新绘制画布和图形,造成视觉冻结和一些延迟 总而言之,问题在于: 我想知道是否有办法在WX Frame
有什么想法吗?这只是答案的一半,因为(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中执行此操作并没有太大的不同。这是一个不错的解决方案,但它没有解决在调整大小后重新绘制绘图的问题。但是,如果event.type()
是MouseButtonRelease
或nonclientreamousebuttonrelease
(受启发),则可以通过运行self.canvas.do\u resize\u now()
来解决此问题。do\u resize\u now
如果事件的类型为WindowStateChange
,则还应调用。此外,如果画布位于QDockWidget
中,则信号和可能需要立即调整大小。
。此外,在调用super(MyFigureCanvas,self)之前,通过比较新大小和以前的大小来检查画布是否已实际调整大小可能是一个好主意。resizeEvent
,否则,绘图在某些情况下将被重新绘制,即使其大小没有改变。最后,QTimer.singleShot(0,do\u resize\u now)
可能必须执行,而不是在某些情况下直接调用do\u resize\u now
(始终调用QTimer.singleShot
),因为画布大小的更新可能已在事件队列中排队。@hellogoodbay此回答使用一个按钮,必须按下该按钮才能触发重画。相反,如果您希望自动重新绘制,那么所有这些点都将适用。