在主窗口工具栏中嵌入带有自定义导航工具栏操作的 matplotlib

Posted

技术标签:

【中文标题】在主窗口工具栏中嵌入带有自定义导航工具栏操作的 matplotlib【英文标题】:embed matplotlib with custom Navigation toolbar actions in the Mainwindow toolbar 【发布时间】:2021-09-13 17:36:21 【问题描述】:

我试图不使用导航工具栏,而是想在主窗口工具栏中添加这些操作。以下是自定义示例:

import sys
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5.QtWidgets import QToolBar, QMainWindow, QAction, qApp, QApplication
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QIcon
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure

class MplCanvas(FigureCanvasQTAgg):

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


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        zoomact = QAction(QIcon('zoom.png'), 'zoom', self)
        zoomact.setShortcut('Ctrl+z')
        zoomact.triggered.connect(self.zoom)

        self.toolbar = self.addToolBar('zoom')
        self.toolbar.addAction(zoomact)

        self.sc = MplCanvas(self, width=5, height=4, dpi=100)
        self.sc.axes.plot([0,1,2,3,4], [10,1,20,3,40])

        #
        toolbar = NavigationToolbar(self.sc, self)
        
        """Here I don't want to use the NavigationToolbar, but custom actions in the 
            toolbar. So I don't want to show the NavigationToolbar"""
            
        "Is there any custom function in the Figure canvas"    
            

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(toolbar)
        layout.addWidget(self.sc)

        # Create a placeholder widget to hold our toolbar and canvas.
        widget = QtWidgets.QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        self.show()

    "Customize function for a specific figure"
    def zoom(self):
        """here, I want to call the specific zoom function from NavigationToolbar
            to apply to this specific FigureCanvas using lambda function"""
        # My trial. I don't know, I cant figure it out :)
        lambda sc: NavigationToolbar2QT.toolitems["zoom"](self.sc, self)
            
    def home(self):
        pass    
    
    def Editaxis(self):
        pass
    
    def configuresubplots(self):
        pass
    
    def save(self):
        pass
    
    def leftbuttonpans(self):
        pass
    
    def backtopreviousview(self):
        pass
        
    def forwardtonextview(self):
        pass

app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()

所以,

我想隐藏 NavigationToolbar 而不使用它 然后,在主窗口工具栏中创建自定义操作,可以对画布中的图形进行操作,例如缩放、编辑轴......等。

【问题讨论】:

【参考方案1】:

您必须将 None 作为 NavigationToolbar2QT 的父级传递:

import sys
import matplotlib

matplotlib.use("Qt5Agg")

from PyQt5.QtWidgets import QAction, QApplication, QMainWindow, QVBoxLayout, QWidget
from PyQt5.QtGui import QIcon

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT
from matplotlib.figure import Figure


class MplCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        print("Text: Name of method")
        for text, _, _, callback in NavigationToolbar2QT.toolitems:
            if isinstance(text, str):
                print(f"text: callback")

        self.sc = MplCanvas(self, width=5, height=4, dpi=100)
        self.mpl_toolbar = NavigationToolbar2QT(self.sc, None)

        zoomact = QAction(QIcon("zoom.png"), "zoom", self)
        zoomact.setShortcut("Ctrl+z")
        zoomact.triggered.connect(self.mpl_toolbar.zoom)

        self.toolbar = self.addToolBar("zoom")
        self.toolbar.addAction(zoomact)

        self.sc.axes.plot([0, 1, 2, 3, 4], [10, 1, 20, 3, 40])

        widget = QWidget()
        self.setCentralWidget(widget)
        layout = QVBoxLayout(widget)
        layout.addWidget(self.sc)


def main():
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec_()


if __name__ == "__main__":
    main()

另一种选择是从 NavigationToolbar2QT 中删除 QActions:

import sys
import matplotlib

matplotlib.use("Qt5Agg")

from PyQt5.QtWidgets import QAction, QApplication, QMainWindow, QVBoxLayout, QWidget
from PyQt5.QtGui import QIcon

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT
from matplotlib.figure import Figure


class MplCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        print("Text: Name of method")
        for text, _, _, callback in NavigationToolbar2QT.toolitems:
            if isinstance(text, str):
                print(f"text: callback")

        self.sc = MplCanvas(self, width=5, height=4, dpi=100)
        self.toolbar = NavigationToolbar2QT(self.sc, self)
        self.addToolBar(self.toolbar)
        self.toolbar.clear()

        zoomact = QAction(QIcon("zoom.png"), "zoom", self)
        zoomact.setShortcut("Ctrl+z")
        zoomact.triggered.connect(self.toolbar.zoom)

        self.toolbar.addAction(zoomact)

        self.sc.axes.plot([0, 1, 2, 3, 4], [10, 1, 20, 3, 40])

        widget = QWidget()
        self.setCentralWidget(widget)
        layout = QVBoxLayout(widget)
        layout.addWidget(self.sc)


def main():
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec_()


if __name__ == "__main__":
    main()

【讨论】:

以上是关于在主窗口工具栏中嵌入带有自定义导航工具栏操作的 matplotlib的主要内容,如果未能解决你的问题,请参考以下文章

在窗口中切换自定义视图

php 渲染嵌入在自定义内容中的所有ReCaptcha Hustle弹出窗口。如果带有ReCaptcha(Formidable Forms)的表单嵌入在Popup中,则为ReCap

导航抽屉和工具栏出现在初始屏幕中

在构建带有关联 Swift 库的 Swift 命令行工具时,为啥要嵌入框架?

使用 UINavigationController 工具栏的替代方法

如何在导航控制器中自定义工具栏