如何为Matplotlib图添加剪贴板支持?

17
在MATLAB中,有一个非常方便的选项可以将当前图形复制到剪贴板。虽然Python/numpy/scipy/matplotlib是MATLAB的一个很好的替代品,但这个选项却不幸地缺失了。
是否可以轻松地将此选项添加到Matplotlib图形中?最好是,所有MPL图形应自动受益于此功能。
我正在使用MPL的Qt4Agg后端,并且使用PySide。
5个回答

14
可以。思路是用自定义的plt.figure替换默认值(这种技术称为monkey patching),并注入一个键盘处理程序以将图形复制到剪贴板。以下代码将允许您通过按Ctrl+C将任何MPL图形复制到剪贴板:
import io
import matplotlib.pyplot as plt
from PySide.QtGui import QApplication, QImage

def add_clipboard_to_figures():
    # use monkey-patching to replace the original plt.figure() function with
    # our own, which supports clipboard-copying
    oldfig = plt.figure

    def newfig(*args, **kwargs):
        fig = oldfig(*args, **kwargs)
        def clipboard_handler(event):
            if event.key == 'ctrl+c':
                # store the image in a buffer using savefig(), this has the
                # advantage of applying all the default savefig parameters
                # such as background color; those would be ignored if you simply
                # grab the canvas using Qt
                buf = io.BytesIO()
                fig.savefig(buf)
                QApplication.clipboard().setImage(QImage.fromData(buf.getvalue()))
                buf.close()

        fig.canvas.mpl_connect('key_press_event', clipboard_handler)
        return fig

    plt.figure = newfig

add_clipboard_to_figures()

请注意,如果您想在交互式会话中使用from matplotlib.pyplot import *,则需要在执行上述代码之后这样做,否则您导入到默认命名空间的figure将是未修补的版本。

对我来说,似乎我无法通过 fig.savefig(buf, format='svg') 选择格式。我得到的图像仍然是位图图像。我正在使用 Python 36 和 Matplotlib 2.2.2,在 Win 7 64 上使用 Qt4Agg 后端。 - Alex
我认为这是因为QImage将其呈现为位图。所以真正的问题是,如何复制粘贴矢量格式的图像,例如SVG? - Alex

8
EelkeSpaak的解决方案被打包在一个不错的模块中: addcopyfighandler 只需通过pip install addcopyfighandler安装,并在导入matplotlib或pyplot后导入该模块即可。

1
这个建议的更详细的答案请参见:https://dev59.com/MVwZ5IYBdhLWcg3wTO3r#63382231 - emgf_co

3

我通过在matplotlibrc文件中添加toolbar: toolmanager来启用了使用ctrl-c将图形复制到剪贴板的功能。

  1. 输入以下命令来定位你的rc文件
  import matplotlib
  print(matplotlib.matplotlib_fname())

在Python解释器中。 然后粘贴。
toolbar: toolmanager

使用您喜爱的编辑器将内容写入文件中。 或者,以下bash单行命令也可以完成此操作:
echo "toolbar: toolmanager" >> $(python -c "import matplotlib;print(matplotlib.matplotlib_fname())")

请注意,这需要针对每个Python解释器进行操作。因此,如果您创建了一个新的Anaconda环境,则必须重复此过程。


2

最后一条评论非常有用。

  1. 使用以下命令安装软件包:

    pip install addcopyfighandler

  2. 在导入matplotlib之后导入模块,例如:

    import matplotlib.pyplot as plt
    import addcopyfighandler

  3. 使用ctr + C将图形复制到剪贴板中

享受吧。


1
如果您解释一下import matplotlib.pyplot as pltimport addcopyfighandler之间的两行代码实际上实现了什么以及为什么它们是必要的,那么这个答案将更加完整(且信息量更大、更值得尊重)。 - Bernd Wechner
谢谢。事实上,这两行是不必要的。我已经将它们删除了。 - emgf_co

2

EelkeSpaak的回答中描述的解决方案的基础上,我们可以编写一个函数来完成这项工作,而不是猴子补丁matplotlib的Figure类:

import io
import matplotlib.pyplot as plt
import numpy as np

from PyQt5.QtGui import QImage
from PyQt5.QtWidgets import QApplication

# Example figure.
fig, ax = plt.subplots()
X = np.linspace(0, 2*np.pi)
Y = np.sin(X)
ax.plot(X, Y)

def add_figure_to_clipboard(event):
    if event.key == "ctrl+c":
       with io.BytesIO() as buffer:
            fig.savefig(buffer)
            QApplication.clipboard().setImage(QImage.fromData(buffer.getvalue()))

fig.canvas.mpl_connect('key_press_event', add_figure_to_clipboard)

请注意,此变体使用Qt5。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接