如何将 Seaborn 绘图集成到 Tkinter GUI

Posted

技术标签:

【中文标题】如何将 Seaborn 绘图集成到 Tkinter GUI【英文标题】:How can I integrate Seaborn plot into Tkinter GUI 【发布时间】:2019-09-04 22:37:06 【问题描述】:

我正在尝试在 Tkinter 中使用 Seaborn 进行绘图。到目前为止,我的方法是不同的变体,我无法让它发挥作用。

我尝试了 matplotlib.use("Agg"),它在页面上的正常 Matplotlib 图形中运行良好,但似乎不适用于 Seaborn 图形

matplotlib.use("TkAgg") # 'Agg' doesnt work either
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import seaborn as sns
import tkinter as tk

def graphspage():
    pf = tk.Tk()
    pf.geometry("1000x800")


### Works
    f = Figure(figsize=(5, 5), dpi=100)
    a = f.add_subplot(111)
    a.plot(df['date'],daily_drawdown, 'b-',df['date'], daily_drawdownbm, 'k-', linewidth=1)
    f.tight_layout()

    canvas = FigureCanvasTkAgg(f,pf)
    canvas.get_tk_widget().grid(row=1,column=1)

### Doesnt Work
    pct = diststats()[4]
    pctbm = diststats()[5]
    f = Figure(figsize=(5, 5), dpi=100)
    a = f.add_subplot(111)
    a.sns.distplot(pct,label = 'Portfolio')
    a.sns.distplot(pctbm,axlabel='Distribution of returns',label='Benchmark')

    canvas = FigureCanvasTkAgg(f,pf)
    canvas.get_tk_widget().grid(row=2,column=1)

graphspage()

【问题讨论】:

你有没有看到任何在 tkinter 中使用 Seaborn 的例子? 而不是a.sns.distplot(pct,label = 'Portfolio'),它必须是sns.distplot(pct,label = 'Portfolio', ax=a) 创建我们可以运行的代码。现在有一些dfdiststats() 所以我们不能运行它。 【参考方案1】:

如果我没记错的话,OP 的原始代码只缺少canvas.draw()furas 也表明了这一点。我最近发现很难找到一个完整的例子来说明如何在 Tkinter GUI 上使用 Seaborn 进行绘图,尤其是如何在画布上重绘。

所以,让我为您提供一个完整的工作但最小的 sn-p 程序,该程序最初在每次按键时都绘制和重绘。

import tkinter
from typing import Callable

import numpy as np
import seaborn as sns
from matplotlib.backend_bases import key_press_handler
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure


def init_gui(root, update_function: Callable) -> FigureCanvasTkAgg:
    def event_key_press(event):
        print("you pressed ".format(event.key))
        update_function()
        key_press_handler(event, canvas)

    # create empty figure and draw
    init_figure = create_figure()
    canvas = FigureCanvasTkAgg(init_figure, master=root)
    canvas.draw()
    canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
    # call key press event
    canvas.mpl_connect("key_press_event", event_key_press)
    return canvas


def create_figure() -> Figure:
    # generate some data
    matrix = np.random.randint(20, size=(10, 10))
    # plot the data
    figure = Figure(figsize=(6, 6))
    ax = figure.subplots()
    sns.heatmap(matrix, square=True, cbar=False, ax=ax)
    return figure


def redraw_figure():
    figure = create_figure()
    canvas.figure = figure
    canvas.draw()


sns.set()
root = tkinter.Tk()
canvas = init_gui(root, update_function=redraw_figure)

tkinter.mainloop()

我使用了一些matplotlib提供的example code。

这是上面的代码在执行和按下某些键时的样子:

【讨论】:

我有一个错误:AttributeError: 'NoneType' object has no attribute 'is_saving' 当我按下键盘时【参考方案2】:

我拿了example from Seaborn page - 所以我可以运行它 - 我输入了 tkinter

create_plot 中的代码使用 matplotlibseaborn 创建绘图并返回 figure。 稍后这段代码将figure 添加到 tkinter 的窗口

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack()

示例不需要matplotlib.use('TkAgg') 也不需要matplotlib.use('Agg')

tkinter.Label,Seaborn 的情节和tkinter.Button,但我也有NavigationToolbar2Tk 的例子

完整代码:

# seaborn in matplotlib - tkinter doesn't need it
#import matplotlib
#matplotlib.use('TkAgg')

# embed matplotlib in tkinter 
import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

# seaborn example
from string import ascii_letters
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

def create_plot():
    sns.set(style="white")

    # Generate a large random dataset
    rs = np.random.RandomState(33)
    d = pd.DataFrame(data=rs.normal(size=(100, 26)),
                     columns=list(ascii_letters[26:]))

    # Compute the correlation matrix
    corr = d.corr()

    # Generate a mask for the upper triangle
    mask = np.zeros_like(corr, dtype=np.bool)
    mask[np.triu_indices_from(mask)] = True

    # Set up the matplotlib figure
    f, ax = plt.subplots(figsize=(11, 9))

    # Generate a custom diverging colormap
    cmap = sns.diverging_palette(220, 10, as_cmap=True)

    # Draw the heatmap with the mask and correct aspect ratio
    sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,
                square=True, linewidths=.5, cbar_kws="shrink": .5)

    return f

# --- main ---

root = tkinter.Tk()
root.wm_title("Embedding in Tk")

label = tkinter.Label(root, text="Matplotlib with Seaborn in Tkinter")
label.pack()

fig = create_plot()

canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack()

button = tkinter.Button(root, text="Quit", command=root.destroy)
button.pack()

tkinter.mainloop()

【讨论】:

以上是关于如何将 Seaborn 绘图集成到 Tkinter GUI的主要内容,如果未能解决你的问题,请参考以下文章

Seaborn:如何在绘图的 X 轴上的每个值之后添加一个“%”符号,而不是将值转换为百分比? [复制]

数据可视化专题——Seaborn简介

Seaborn 热图:在绘图顶部移动颜色条

使用 seaborn 绘图时,如何为色调参数指定多个变量?

python 3.x tkinter,将来自opencv cv2的帧集成到tkinter窗口中

使用 *args 和 seaborn 绘图时如何显示所有图例