使用Matplotlib的导航工具栏,我有一个相对简单的情况。我希望能够在图形更新之间保持先前的缩放值,摄像机平移等。我已经将PyQt5嵌入到这里(我在我的项目中使用),以防两者之间需要一些额外的链接。非常感谢你看看!
import sys
import os
import random
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QGridLayout, QFileDialog, QPushButton
from numpy import arange
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.fig = fig ###
self.axes = fig.add_subplot(111)
self.axes.hold(False)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def compute_initial_figure(self):
pass
class MyDynamicMplCanvas(MyMplCanvas):
def __init__(self, *args, **kwargs):
MyMplCanvas.__init__(self, *args, **kwargs)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.update_figure)
timer.start(1000)
def compute_initial_figure(self):
self.axes.plot([0, 1, 2, 3], [1, 2, 0, 4], 'b')
def update_figure(self):
l = [random.randint(0, 10) for i in range(4)]
self.axes.cla()
self.axes.plot([0, 1, 2, 3], l, 'b')
self.draw()
class P1(QtWidgets.QWidget):
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QGridLayout(self)
self.plot_canvas = MyDynamicMplCanvas(self, width=5, height=4, dpi=100)
self.navi_toolbar = NavigationToolbar(self.plot_canvas, self)
layout.addWidget(self.plot_canvas, 1, 1, 1, 1)
layout.addWidget(self.navi_toolbar, 2, 1, 1, 1)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.stack = QtWidgets.QStackedWidget(self)
P1f = P1(self)
self.stack.addWidget(P1f)
self.setCentralWidget(self.stack)
if __name__ == '__main__':
qApp = QtWidgets.QApplication(sys.argv)
aw = MainWindow()
aw.show()
sys.exit(qApp.exec_())
答案 0 :(得分:1)
这里的大恶棍是axes.hold(False)
和axes.cla()
。他们负责清除轴和图形,这通常会重置绘图视图。
有了这些,你可以正确使用self.axes.autoscale(enable=False)
,我建议你在compute_initial_figure()
的第一个情节后放置,所以情节在开始时至少有点缩放。
然后,为了能够清除以前的图表,您可以为MyMplCanvas
类创建另一个属性,可能self.plotted_line
或类似的内容,使用None
进行初始化。每次拨打self.axes.plot(...)
时,都会将返回值分配给self.plotted_line
,如下所示:self.plotted_line, = self.axes.plot(...)
。注意self.plotted_line
之后的逗号,这是仅指定第一个返回值的方法之一,也就是您感兴趣的那个。
最后,在每个新情节之前,检查并致电
if self.plotted_line is not None:
self.plot.remove()
将有效删除以前的情节。
画布类看起来像这样(变化很小)。
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.fig = fig ###
self.axes = fig.add_subplot(111)
self.plotted_line = None
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def compute_initial_figure(self):
pass
class MyDynamicMplCanvas(MyMplCanvas):
def __init__(self, *args, **kwargs):
MyMplCanvas.__init__(self, *args, **kwargs)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.update_figure)
timer.start(1000)
def compute_initial_figure(self):
self.plotted_line, = self.axes.plot([0, 1, 2, 3], [1, 2, 0, 4], 'b')
self.axes.autoscale(enable=False)
def update_figure(self):
l = [random.randint(0, 10) for i in range(4)]
if self.plotted_line is not None:
self.plotted_line.remove()
self.plotted_line, = self.axes.plot([0, 1, 2, 3], l, 'b')
self.draw()
答案 1 :(得分:0)
可以通过将mpl'draw_event'与以下内容直接连接来存储缩放值:
def __init__(self, parent=None, width=5, height=4, dpi=100):
...
self.mpl_connect('draw_event', self.on_draw)
def on_draw(self, event):
self.xlim = self.axes.get_xlim()
self.ylim = self.axes.get_ylim()
,然后在plot()调用后恢复:
def update_figure(self):
...
self.axes.plot([0, 1, 2, 3], l, 'b')
self.axes.set_xlim(self.xlim)
self.axes.set_ylim(self.ylim)
...
https://matplotlib.org/users/event_handling.html
完整代码:
import random
import sys
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QGridLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.fig = fig ###
self.axes = fig.add_subplot(111)
self.axes.hold(False)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
self.xlim = self.axes.get_xlim()
self.ylim = self.axes.get_ylim()
self.mpl_connect('draw_event', self.on_draw)
def on_draw(self, event):
self.xlim = self.axes.get_xlim()
self.ylim = self.axes.get_ylim()
def compute_initial_figure(self):
pass
class MyDynamicMplCanvas(MyMplCanvas):
def __init__(self, *args, **kwargs):
MyMplCanvas.__init__(self, *args, **kwargs)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.update_figure)
timer.start(1000)
def compute_initial_figure(self):
self.axes.plot([0, 1, 2, 3], [1, 2, 0, 4], 'b')
def update_figure(self):
l = [random.randint(0, 10) for i in range(4)]
self.axes.cla()
self.axes.plot([0, 1, 2, 3], l, 'b')
self.axes.set_xlim(self.xlim)
self.axes.set_ylim(self.ylim)
self.draw()
class P1(QtWidgets.QWidget):
def __init__(self, parent=None):
super(P1, self).__init__(parent)
layout = QGridLayout(self)
self.plot_canvas = MyDynamicMplCanvas(self, width=5, height=4, dpi=100)
self.navi_toolbar = NavigationToolbar(self.plot_canvas, self)
layout.addWidget(self.plot_canvas, 1, 1, 1, 1)
layout.addWidget(self.navi_toolbar, 2, 1, 1, 1)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.stack = QtWidgets.QStackedWidget(self)
P1f = P1(self)
self.stack.addWidget(P1f)
self.setCentralWidget(self.stack)
if __name__ == '__main__':
qApp = QtWidgets.QApplication(sys.argv)
aw = MainWindow()
aw.show()
sys.exit(qApp.exec_())