【问题标题】:How to combine two subplots in one tkinter window?如何在一个 tkinter 窗口中组合两个子图?
【发布时间】:2020-02-11 11:09:56
【问题描述】:

我想在一个 tkinter 窗口中显示 两个 matplotlib 图在一个 tkinter 窗口中。到目前为止,我需要两个不同的代码。如何将代码合二为一?我已经使用下面的 powerpoint 创建了所需的结果。我已经用 subplot 尝试过,不幸的是没有成功: plt.subplots(2,1, figsize=(20,10)) and plt.subplots(1,1, figsize=(20,10) ))

我的第一个代码:

# ___________________________________________________________________________
# Library 
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk 
import tkinter as tk
import numpy as np

# ___________________________________________________________________________
# Carwash Array
Carwash_km = np.array([1,4,500,1500,2800,2960,2700,5,2000,2000,3100,4000,4150,4150])
Carwash_cost = np.array([5,1000,1000,2100,3000,3150,3150,20,50,600,3500,3800,3960,3700])

# Fuel Array
Fuel_km = np.array([2,5,600,2600,3900,3970,3800,6,3000,3000,4200,5000,5260,5260])
Fuel_cost = np.array([6,2000,2000,3200,4000,4260,4260,30,60,700,4600,4900,4070,4800])

# Maintenance Array
Maintenance_km = np.array([0,3,400,400,1700,1850,1600,4,1000,1000,2000,3000,3040,3040])
Maintenance_cost = np.array([4,500,500,1000,2000,2040,2040,10,40,500,2400,2700,2850,2600])

# ___________________________________________________________________________
# Main
Vis = tk.Tk()
Vis.title("Main") # titel

# ___________________________________________________________________________
# Plot
fig, ax = plt.subplots(1, 1, figsize=(20,5), facecolor = "white")


Plot_Carwash_cost = plt.bar(Carwash_km, Carwash_cost, 
                             bottom=0, 
                             color="#BDD7EE", 
                             ec="black", 
                             width=100, 
                             label="Carwash_cost")


Plot_Carwash_cost2 = plt.bar(Maintenance_km, -Maintenance_cost, 
                                 bottom=-0, 
                                 color="#C5E0B4",
                                 ec="black",
                                 width=100, 
                                 label="Maintenance_cost")

Plot_Fuel = plt.scatter(Fuel_km, Fuel_cost, 
                             marker="^", 
                             s=150, 
                             color="#C00000", 
                             edgecolors="black", 
                             zorder=3, 
                             label="Fuel_cost")

ax.spines["bottom"].set_position("zero")
ax.spines["top"].set_color("none")
ax.spines["right"].set_color("none")
ax.spines["left"].set_color("none")
ax.tick_params(axis="x", length=20)

_, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
ax.set_xlim(-15, xmax)
ax.set_ylim(ymin, ymax+10) # legend
ax.text(xmax, -5, "km", ha="right", va="top", size=14)
plt.legend(ncol=5, loc="upper left")
plt.tight_layout() 

# ___________________________________________________________________________
# Canvas, Toolbar
canvas = FigureCanvasTkAgg(fig, master=Vis)
canvas.draw() # TK-Drawingarea
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
canvas._tkcanvas.pack(side = tk.TOP, fill = tk.BOTH, expand = True)

toolbar = NavigationToolbar2Tk(canvas, Vis)
toolbar.update()

Vis.mainloop()

我的第二个代码:

# ___________________________________________________________________________
# Library
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk 
import tkinter as tk
import numpy as np

# ___________________________________________________________________________
# 1 Array
Beg1 = np.array([1,4,500,1500,2800,2960,2700,5,2000,2000,3100,4000,4150,4150])
End1 = np.array([2,5,600,2600,3900,3970,3800,6,3000,3000,4200,5000,5260,5260])

# 2 Array
Beg2 = np.array([5,1000,1000,2100,3000,3150,3150,20,50,600,3500,3800,3960,3700])
End2 = np.array([6,2000,2000,3200,4000,4260,4260,30,60,700,4600,4900,4070,4800])

# 3 Array
Beg3 = np.array([0,3,400,400,1700,1850,1600,4,1000,1000,2000,3000,3040,3040])
End3 = np.array([4,500,500,1000,2000,2040,2040,10,40,500,2400,2700,2850,2600])

# ___________________________________________________________________________
# detail
Vis2 = tk.Tk()
Vis2.title("detail") # titel

# ___________________________________________________________________________
# Plot
fig, ax = plt.subplots(2, 1, figsize=(20,10), facecolor = "white")

Plot_1 = plt.barh(len(Beg1)+np.arange(len(Beg2)),  End2-Beg2+500, 
                   left=Beg2,
                   height=0.9,
                   color='red',
                   alpha=0.5)

Plot_2 = plt.barh(range(len(Beg1)),  End1-Beg1, 
                    left=Beg1,
                    height=0.9,
                    color='#BDD7EE')

Plot_3 = plt.barh(len(Beg1)+len(Beg2)+np.arange(len(Beg3)),  End3-Beg3+500, 
                   left=Beg3,
                   height=0.9,
                   color="#C5E0B4")

plt.tight_layout()

# ___________________________________________________________________________
# Canvas, Toolbar
canvas = FigureCanvasTkAgg(fig, master = Vis2)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
canvas._tkcanvas.pack(side = tk.TOP, fill = tk.BOTH, expand = True)

toolbar = NavigationToolbar2Tk(canvas, Vis2)
toolbar.update()

Vis2.mainloop()

【问题讨论】:

    标签: python matplotlib tkinter data-visualization


    【解决方案1】:

    简短的回答是创建两个Frame 小部件,并将您的FigureCanvasTkAgg 主设置为每个Frame

    ...
    frame1 = tk.Frame(Vis)
    frame2 = tk.Frame(Vis)
    frame1.pack()
    frame2.pack()
    
    ...
    canvas = FigureCanvasTkAgg(fig, master = frame1)
    ...
    canvas2 = FigureCanvasTkAgg(fig, master = frame2)
    ...
    
    Vis.mainloop()
    

    更好的方法是创建一个继承自Frame 的类并处理FigureNavigationToolBar 的创建。根据您的需要,它可能是这样的:

    from matplotlib.figure import Figure #use Figure instead of pyplot if you are embedding into tkinter
    
    class GraphFrame(tk.Frame):
        def __init__(self, master=None, **kwargs):
            super().__init__(master, **kwargs)
            self.fig = Figure()
            self.ax = self.fig.add_subplot(111)
            self.canvas = FigureCanvasTkAgg(self.fig, master=self)
            self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
            self.toolbar = NavigationToolbar2Tk(self.canvas, self)
            self.toolbar.update()
    

    然后你就可以在同一个根窗口Vis下轻松创建新的绘图区了:

    Vis = tk.Tk()
    
    graph1 = GraphFrame(Vis)
    graph1.pack()
    graph1.ax.bar(Carwash_km, Carwash_cost, ...)
    graph1.ax.bar(Maintenance_km, -Maintenance_cost, ...)
    graph1.ax.scatter(Fuel_km, Fuel_cost, ...)
    
    graph2 = GraphFrame(Vis)
    graph2.pack()
    graph2.ax.barh(...)
    graph2.ax.barh(...)
    graph2.ax.barh(...)
    
    Vis.mainloop()
    

    【讨论】:

    • 谢谢,我去测试一下。
    【解决方案2】:

    #对不起

    #in

    类 GraphFrame(tk.Frame):

    def __init__(self, master=None, **kwargs):
    
        super().__init__(master, **kwargs)
    
        self.fig = Figure()
    

    我认为正确的语法是:

    类 GraphFrame(tk.Frame):

    def __init__(self, master=None, **kwargs):
    
        super().__init__(master, **kwargs)
    
        self.fig = plt.figure()
    

    我说的对吗?

    【讨论】:

    • 不,这是不正确的。这并不能回答 OP 的问题。
    猜你喜欢
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 2016-12-25
    • 1970-01-01
    • 2022-09-28
    • 2013-01-08
    • 2020-11-20
    相关资源
    最近更新 更多