编辑:
我决定重写它以包含我的问题的工作示例。虽然这很长,但我希望它在未来对许多人有用。
import sys
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setGeometry(100, 100, 640, 480)
showButton = QPushButton('Show')
toolbarShowButton = self.addToolBar('Show button toolbar')
toolbarShowButton.addWidget(showButton)
self.connect(showButton, SIGNAL('clicked()'), self.showButtonClicked)
self.graphLabel = GraphCanvas(self);
self.setCentralWidget(self.graphLabel)
def showButtonClicked(self):
self.graphLabel.drawGraph()
def resizeEvent(self, event):
try:
self.graphLabel.setFig()
except AttributeError:
pass
class GraphCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
self.fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = self.fig.add_subplot(111)
FigureCanvas.__init__(self, self.fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QSizePolicy.Expanding,
QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
self.background = None
def drawGraph(self):
self.axes.cla()
self.someplot = self.axes.plot(range(1,5), range(1,5))
self.redVert, = self.axes.plot(None, None, 'r--')
self.greenVert, = self.axes.plot(None, None, 'g--')
self.yellowVert, = self.axes.plot(None, None, 'y--')
self.verticalLines = (self.redVert, self.greenVert, self.yellowVert)
self.fig.canvas.mpl_connect('motion_notify_event', self.onMove)
self.draw()
self.background = self.fig.canvas.copy_from_bbox(self.axes.bbox)
def onMove(self, event):
# cursor moves on the canvas
if event.inaxes:
# restore the clean background
self.fig.canvas.restore_region(self.background)
ymin, ymax = self.axes.get_ylim()
x = event.xdata - 1
# draw each vertical line
for line in self.verticalLines:
line.set_xdata((x,))
line.set_ydata((ymin, ymax))
self.axes.draw_artist(line)
x += 1
self.fig.canvas.blit(self.axes.bbox)
def setFig(self):
'''
Draws the canvas again after the main window
has been resized.
'''
try:
# hide all vertical lines
for line in self.verticalLines:
line.set_visible(False)
except AttributeError:
pass
else:
# draw canvas again and capture the background
self.draw()
self.background = self.fig.canvas.copy_from_bbox(self.axes.bbox)
# set all vertical lines visible again
for line in self.verticalLines:
line.set_visible(True)
def main():
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
if __name__ == '__main__': main()
代码说明
我有一个QMainWindow
带有“显示”按钮的工具栏的基本工具。主窗口还为图形创建画布matplotlib
并将其设置为中央小部件。
当用户点击“显示”按钮时,通过调用 的drawGraph()
方法显示一些数据GraphCanvas
。在实际程序中,数据会根据用户在单击按钮之前选择要显示的内容而变化。该方法resizeEvent()
基本上再次绘制图形以适应新的中心小部件大小。
该drawGraph()
方法创建了四个图,其中第一个具有数据,因此它是可见的。最后两行绘制图形并将静态背景保存到变量self.background
中。
当用户在画布上移动鼠标时,首先加载背景。我想保存和加载静态背景以使图形绘制得更快。之后,最后三个图动态获取它们的数据,并显示为 3 条随鼠标光标移动的垂直线。
问题
1)随着您不断点击“显示”按钮,图形会逐渐变慢。如果您尝试敲击它 50 次并在图形上移动鼠标,您会发现垂直线更加滞后。当真实图形中有更多的动态图和注释等时,只需单击几下,程序就会变得无法使用。
更聪明的人可能会说出为什么会发生这种减速,但我猜以前加载的图形保存在内存中的某个位置,并且可能绘制在新创建的图形下方。而且堆栈只会越来越大。
2)启动程序后立即显示该图。没什么大不了的,但在单击按钮之前,我更喜欢那里的空白区域。
尝试了一个解决方案
我尝试的是将这两行从def __init__(self)
ofclass MainWindow
移到def showButtonClicked(self)
:
self.graphLabel = GraphCanvas(self);
self.setCentralWidget(self.graphLabel)
所以它现在看起来像这样:
def showButtonClicked(self):
self.graphLabel = GraphCanvas(self);
self.setCentralWidget(self.graphLabel)
self.graphLabel.drawGraph()
所以我只有在按下按钮后才创建了这个图形。这解决了减速问题,但带来了另一个问题。现在,当您点击“显示”按钮并在画布上移动鼠标时,会加载已保存的图形背景,但原始尺寸为 5 x 4 英寸,我们一团糟。所以基本上背景不是以绘制图形的大小保存的,而是以创建它的大小保存的。
但是,如果我调整窗口大小,一切正常。但是下次我单击“显示”按钮时,问题再次出现,我需要再次调整窗口大小。
我需要的
无论单击“显示”按钮多少次,我都需要使这个东西流畅地工作并且看起来应该是它应该的样子。另外,我希望在第一次单击“显示”按钮之前没有显示该图形,并且从那时起直到程序关闭为止都可见。
当单击“显示”按钮时,我会遇到一些技巧,例如将窗口大小调整一个像素,但这不是正确的方法,是吗?
任何想法和建议都非常受欢迎。谢谢你。