简体   繁体   English

如何在 PyQt5 应用程序中从 Matplotlib NavigationToolbar 更改默认文件名?

[英]How to change default filename from Matplotlib NavigationToolbar in a PyQt5 application?

I am writing an application in Python 3.5 & PyQT 5. In this application I have an embedded matplotlib canvas and an embedded matplotlib NavigationToolbar.我正在用 Python 3.5 和 PyQT 5 编写一个应用程序。在这个应用程序中,我有一个嵌入式 matplotlib 画布和一个嵌入式 matplotlib NavigationToolbar。 The application measures some data and then plots them.应用程序测量一些数据,然后绘制它们。 The user at some point wants to export the plot and save it into a ".png" file somewhere and then measure something new.用户在某个时候想要导出绘图并将其保存到某个地方的“.png”文件中,然后测量一些新的东西。

For this, I have been using the "floppy"/"save" icon on the NavigationToolbar and it works well.为此,我一直在使用导航工具栏上的“软盘”/“保存”图标,它运行良好。 However, when I click it, it opens a dialog at the root folder of the program (or last opened folder) and pre-fills the name of the saved image as "image.png".但是,当我单击它时,它会在程序的根文件夹(或上次打开的文件夹)中打开一个对话框,并将保存的图像的名称预填充为“image.png”。

I would like to change this pre-filled default name to something custom to my program, such as "measurement_7453243.png" or "2017_01_16_measurement.png".我想将此预填充的默认名称更改为我的程序自定义的名称,例如“measurement_7453243.png”或“2017_01_16_measurement.png”。 Is there a way that would allow me to do this?有没有办法让我这样做?

Idea #1: What I found is the option to use matplotlib.rcParams['savefig.directory'] and use that to set the directory of where the dialog should be opened - not the filename though.想法#1:我发现可以选择使用 matplotlib.rcParams['savefig.directory'] 并使用它来设置应该打开对话框的目录 - 虽然不是文件名。 I cannot seem to find a 'savefig.XXXX' property that would change the default filename.我似乎找不到可以更改默认文件名的“savefig.XXXX”属性。

Idea #2: I could make a custom button in my app outside of the NavigationToolbar, which would run a custom file saving dialog with Qt and then use savefig() to save the figure.想法#2:我可以在我的应用程序中的 NavigationToolbar 之外创建一个自定义按钮,这将使用 Qt 运行自定义文件保存对话框,然后使用 savefig() 保存图形。 But why do that if there is already a nice button that does ALMOST what I want?但是,如果已经有一个很好的按钮几乎可以满足我的要求,为什么还要这样做呢?

Any tips and ideas, as well as "this cannot be done" with proper sources will be greatly appreciated.任何提示和想法,以及“这不能做”与适当的来源将不胜感激。

The default file name is provided by the method FigureCanvasBase.get_default_filename . 默认文件名由方法FigureCanvasBase.get_default_filename You can just monkey patch it after the canvas has been created: 您可以在创建画布后用猴子修补它:

canvas = FigureCanvas(fig)
canvas.get_default_filename = lambda: 'new_default_name.png'

I guess the proper way is subclassing FigureCanvas though, override the method and maybe provide an API to set the default file name. 我想正确的方法是子类化FigureCanvas但是重写该方法,并可能提供API来设置默认文件名。

Here is an example for Qt5Agg using monkey patching, adapted from the matplotlib docs: 这是Qt5Agg使用猴子补丁的示例,改编自matplotlib文档:

from PyQt5.QtWidgets import (
    QMainWindow, QApplication, QWidget, QVBoxLayout)

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import (
    FigureCanvasQTAgg as FigureCanvas,
    NavigationToolbar2QT as NavigationToolbar)


class AppForm(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        main_frame = QWidget()

        fig = Figure((5.0, 4.0), dpi=100)
        ax = fig.add_subplot(111)
        ax.plot([1, 2, 4, 8])

        canvas = FigureCanvas(fig)
        canvas.get_default_filename = lambda: 'new_default_name.png'
        mpl_toolbar = NavigationToolbar(canvas, main_frame)

        vbox = QVBoxLayout()
        vbox.addWidget(canvas)  # the matplotlib canvas
        vbox.addWidget(mpl_toolbar)
        main_frame.setLayout(vbox)
        self.setCentralWidget(main_frame)


app = QApplication(['Test'])
form = AppForm()
form.show()
app.exec_()

Not sure if you can always do this, but in my case the figure instance had a canvas attribute which I could monkeypatch as Goyo suggested. 不确定是否可以始终执行此操作,但是在我的情况下,Figure实例具有canvas属性,我可以按照Goyo的建议进行monkeypatch。

import matplotlib.pyplot as plt
f = plt.figure()
c = f.canvas
my_adventurous_filename = 'figure-III' # irony
c.get_default_filename = lambda : '%s.%s' % (my_adventurous_filename,
                                             c.get_default_filetype())
plt.show()

This was mentioned in Matplotlib-3 documentation and worked for me (Python 3.8.5/TkAgg):这在 Matplotlib-3 文档中提到并且对我有用(Python 3.8.5/TkAgg):

fig, axs = plt.subplots(...)
fig.canvas.set_window_title(my_file_name)

I also set:我还设置了:

matplotlib.rcParams['savefig.format'] = 'svg'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM