Matplotlib 导航工具栏重置 legendstyle

Matplotlib navigation toolbar resets legendstyle

目前我正在开发一个小部件,其中包含来自 matplotlib 的绘图。对于我的用例,我自定义了 matplotlib 的默认导航工具栏(请参见下面的代码)。

import os
import sys
import matplotlib; matplotlib.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg,  NavigationToolbar2QT
from matplotlib.figure import Figure
from matplotlib.lines import Line2D
from PyQt5 import QtCore, QtGui, QtWidgets




class MplCanvas(FigureCanvasQTAgg):


    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.figure=Figure(figsize=(width, height), dpi=dpi)
        super(MplCanvas, self).__init__(self.figure)


    def initAxes(self):
        self.axes=self.figure.add_subplot(111)
        self.axes.get_xaxis().set_minor_locator(matplotlib.ticker.AutoMinorLocator())
        self.axes.get_yaxis().set_minor_locator(matplotlib.ticker.AutoMinorLocator())
        self.axes.grid(b=True, which='major', color='black', linewidth=1.0)
        self.axes.grid(b=True, which='minor', color='black', linewidth=0.25)




class MainWindow(QtWidgets.QWidget):


    def __init__(self):
        super().__init__()

        self.__setupCanvas()
        self.__setupWidget()

        QtCore.QMetaObject.connectSlotsByName(self)
        self.show()


    def __setupCanvas(self):
        self.canvas=MplCanvas(self, width=5, height=4, dpi=100)
        self.canvas.initAxes()
        self.canvas.mpl_connect('pick_event', self.remove_graph)
        
        self.toolbar=MyNavigationToolbar(self, self.canvas)
        self.toolbar.setIconSize(QtCore.QSize(20, 20))
        

    def __setupWidget(self):
        self.resize(500, 500)
        self.layout=QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.canvas)
        self.layout.addWidget(self.toolbar)
        self.setLayout(self.layout)


    def plot(self,  x, y, label):
        newLine=Line2D(x, y, label=label)
        newLine.set_picker(5)
        self.canvas.axes.plot(x, newLine.get_ydata(), label=label, picker=5)
        self.__generateLegend()


    def __generateLegend(self):
        self.canvas.axes.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left", mode="expand", borderaxespad=0, ncol=3)


    def remove_graph(self, event):
        if self.toolbar.removeGraph:
            self.canvas.axes.lines.remove(event.artist)
            self.__generateLegend()
            self.canvas.draw()
            

    

class MyNavigationToolbar(NavigationToolbar2QT): 


    def __init__(self, parent, canvas):
        workingPaht=str(os.getcwd())
        self.toolitems=(('Home', 'Reset View', workingPaht+'/Icons/home', 'home'),
                        ('Pan', 'Pan View', workingPaht+'/Icons/pan', 'pan'),
                        ('Zoom', 'Zoom', workingPaht+'/Icons/zoom', 'zoom'),
                        ('Subplots_a', 'Edit View', workingPaht+'/Icons/slider', 'configure_subplots'),
                        ('Subplots_b', 'Edit axis, curve and image parameters', workingPaht+'/Icons/graph', 'edit_parameters'),
                        ('Save', 'sollemnes in futurum', workingPaht+'/Icons/save', 'save_figure'),
                        ('Remove', 'Remove Graph', workingPaht+'/Icons/cut', 'remove_graph'))
        
        NavigationToolbar2QT.__init__(self, canvas, parent)
        self._actions['remove_graph'].setCheckable(True)
        self.removeGraph=False
        
    
    def remove_graph(self):
        self.__reset_NavigationToolbar2() 
        self.mode='delete selected graph'
        self.set_message(self.mode) 
        self.removeGraph=True


    def __reset_NavigationToolbar2(self):
        self._active=None
        self._idPress=self.canvas.mpl_disconnect(self._idPress)
        self._idRelease=self.canvas.mpl_disconnect(self._idRelease)
        self.mode=''
        
        self.canvas.widgetlock.release(self)
        self._update_buttons_checked() 

        
    def pan(self, *args): 
        self._actions['remove_graph'].setChecked(False)
        super().pan(*args)


    def zoom(self, *args): 
        self._actions['remove_graph'].setChecked(False)
        super().zoom(*args)
        



if __name__=='__main__':
    app=QtWidgets.QApplication(sys.argv)
    window=MainWindow()
    window.plot([0,1,2,3,4], [10,1,20,3,40], 'test_1')
    window.plot([0,1,2,3,4], [10,10,10,10,10], 'test_2')
    app.exec_()

我的问题是,如果我使用(见图片):导航工具栏-图形选项-(重新)生成图例
我的图例设置/样式已删除。我该如何解决?

在最后一张图片中,您可以看到图例样式已设置为默认样式。 希望你们中的任何人都知道答案。
谢谢。

问题是当您选中“(重新)生成图例”时,代码 运行 会删除您拥有的任何图例,并使用发现的艺术家将其替换为默认图例。

相关代码在

https://github.com/matplotlib/matplotlib/blob/e73d4e056588abc201335d8a491fd9cb37d4c296/lib/matplotlib/backends/qt_editor/figureoptions.py#L237-L246

        if generate_legend:
            draggable = None
            ncol = 1
            if axes.legend_ is not None:
                old_legend = axes.get_legend()
                draggable = old_legend._draggable is not None
                ncol = old_legend._ncol
            new_legend = axes.legend(ncol=ncol)
            if new_legend:
                new_legend.set_draggable(draggable)

这看起来只从现有图例(列数和是否可拖动)中拉出 一些 状态,而不是您正在使用的其他设置。

我将在 github 上创建一个问题,我认为扩展它以更好地克隆配置是一个很好的第一个问题。

https://github.com/matplotlib/matplotlib/issues/17775