PyQt 嵌入式 MatPlotLib 图可以交互吗?

Can a PyQt Embedded MatPlotLib Graph Be Interactive?

我的 GUI 中嵌入了分析数据的堆积条形图,我希望它更具交互性。当用户将鼠标悬停或单击条形图时,应显示绘制值。这可以做到吗?我无法在文档中找到任何相关信息。或者我可以使用 PyGal 之类的东西,但我不知道如何将它嵌入到 PyQt 中。将不胜感激。

最简单的解决方案是使用 matplotlib 事件。无论您使用独立绘图 window 还是嵌入到 GUI 中,它们的工作方式都是一样的。

可以在matplotlib手册的event handling page中找到很好的介绍。

据我所知,默认情况下没有。

我担心,你必须为自己工作一点,因为我不知道一个通​​用的小部件。还有其他 QT 设计器已经提供了更多交互式图表,例如: http://www.taurus-scada.org/en/latest/devel/designer_tutorial.html 但是,据我所知,它并没有提供你想要的东西。我宁愿考虑创建您自己的小部件。

是的,他们绝对可以。 matplotlib 文档有一些有用的代码 (https://matplotlib.org/users/event_handling.html#object-picking),您可以使用 %matplotlib qt #tk, wx, inline#(for notebook) 等在 qt、tk、wx 等界面中以交互方式实现这些代码...如果您 运行 这段代码,我认为它所做的事情与您所追求的非常接近(我正在使用 tk...所以更改为 qt,我想它仍然有效)。 运行 它然后点击散点图上的一个点来触发事件 "onpick" 并显示 'point' 历史:

"""
compute the mean and stddev of 100 data sets and plot mean vs stddev.
When you click on one of the mu, sigma points, plot the raw data from
the dataset that generated the mean and stddev
"""
import numpy as np
import matplotlib.pyplot as plt
%matplotlib tk

X = np.random.rand(100, 1000)
xs = np.mean(X, axis=1)
ys = np.std(X, axis=1)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('click on point to plot time series')
line, = ax.plot(xs, ys, 'o', picker=5)  # 5 points tolerance


def onpick(event):

    if event.artist!=line: return True

    N = len(event.ind)
    if not N: return True


    figi = plt.figure()
    for subplotnum, dataind in enumerate(event.ind):
        ax = figi.add_subplot(N,1,subplotnum+1)
        ax.plot(X[dataind])
        ax.text(0.05, 0.9, 'mu=%1.3f\nsigma=%1.3f'%(xs[dataind], ys[dataind]),
                transform=ax.transAxes, va='top')
        ax.set_ylim(-0.5, 1.5)
    figi.show()
    return True

fig.canvas.mpl_connect('pick_event', onpick)

plt.show()

我对 qt 一点经验都没有,但对于 tk 来说,你似乎可以将 matplotlib 图形发送到 canvas,它们工作得很好 - 所以我假设在 qt 中可能有类似的东西,但根据您的问题,您已经将其嵌入并且刚好在交互之后。


注意 我 运行 遇到了一个花了一段时间才弄清楚的问题 我不知道它在 qt 中是否相同(也许其他人可以确认)...但请注意,您可能需要在绘图时显式设置 picker=True。再一次,我对 qt 真的一无所知,但这里是上面的 tk 中的一个实现,但是在没有 picker=True 的自定义 gui 上将不会交互:

import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure

import Tkinter as tk #for Python 3.x use import tkinter as tk
import ttk #for Python 3.x use from tkinter import ttk

class My_GUI:

    def __init__(self,master):
        self.master=master
        master.title("samplegui")
        f = Figure(figsize=(5,5), dpi=100)
        a = f.add_subplot(111)
        a.scatter(np.random.normal(size=100),np.random.normal(size=100),picker=True)
        canvas1=FigureCanvasTkAgg(f,master)
        canvas1.show()
        canvas1.get_tk_widget().pack(side="top",fill='x',expand=True)
        f.canvas.mpl_connect('pick_event',self.onpick)

        toolbar=NavigationToolbar2TkAgg(canvas1,master)
        toolbar.update()
        toolbar.pack(side='top',fill='x')

    def onpick(self,event):
        #do stuff
        print "My OnPick Event Worked!"
        return True

root=tk.Tk()
gui=My_GUI(root)
root.mainloop()