Tkinter嵌入式图形更改绘图轴

时间:2018-03-12 16:47:42

标签: python pandas user-interface tkinter graph

所以我在这里有一个包含2帧的基本GUI。第一页有两个下拉菜单,用户可以从中选择数据框中的列。它还包括一个按钮,当按下该按钮时,将两个选定列都输出到标签上(这只是为了确保它正确选择)。

我试图让代码执行的操作是,每次在下拉菜单中选择新列时,图表都会使用新绘图进行更新。我认为它就像将它们分配给字符串变量一样简单,但这似乎不起作用。

还有第二页也带有图表,以防更容易在帧中使用此功能,但理想情况下它将保留在同一帧上。

import pandas as pd
import tkinter as tk
#from tkinter import filedialog
from tkinter import ttk

import matplotlib

matplotlib.use("TkAgg")

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg

from matplotlib.figure import Figure

df = pd.DataFrame(
        [[4, 5, 6],
        [7, 8, 9],
        [10, 11, 12]],
        columns=['a', 'b', 'c'])

xList = []
yList = []

Options = df.dtypes.index 

fig = Figure(figsize=(5,4), dpi=100)
ax= fig.add_subplot(111)

LARGE_FONT= ("Verdana", 12)

class GUI(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "GUI")

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (Home, Graph):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(Home)




    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()


class Home(tk.Frame):

    def __init__(self, parent, controller):
        self.controller = controller
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Start Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        def selectXY():
            x = varX.get()            
            y = varY.get()

            ax.clear() 


            X.config(text=x)
            Y.config(text=y)

            xList = df.loc[:,X]
            yList = df.loc[:,Y]


            return xList
            return yList

        #Y axis select
        varY = tk.StringVar(self)
        # initial value
        varY.set('Select Y axis')

        optionY = tk.OptionMenu(self, varY, *Options)

        optionY.pack()

        #X axis select
        varX = tk.StringVar(self)
        # initial value
        varX.set('Select X axis')

        optionX = tk.OptionMenu(self, varX, *Options)

        optionX.pack()

        button2 = tk.Button(self, text="Plot Axes", command = selectXY)

        button2.pack()

        button2 = ttk.Button(self, text="Graph",
                            command=lambda: controller.show_frame(Graph))
        button2.pack()

        Y = ttk.Label(self, text=yList)
        Y.pack()

        X = ttk.Label(self, text=xList)
        X.pack()


        df.plot.scatter(xList, yList, ax=ax)


        canvas = FigureCanvasTkAgg(fig, self)
        canvas.show()
        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)



class Graph(tk.Frame):

    def __init__(self, parent, controller):
        self.controller = controller
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Graph", font=LARGE_FONT)
        label.pack(pady=10,padx=10)


        df.plot.scatter(xList, yList, ax=ax)


        canvas = FigureCanvasTkAgg(fig, self)
        canvas.show()
        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)


        button3 = ttk.Button(self, text="Back",
                            command=lambda: controller.show_frame(Home))
        button3.pack()

app = GUI()
app.mainloop()

1 个答案:

答案 0 :(得分:0)

考虑以下调整:

  1. 将您的图形构建移动到 selectXY 方法中,以便按钮可以在单击时运行它。

  2. 按名称将轴传递到pandas.DataFrame.plot,其中 x y 为字符串值。因此,不需要带有.loc调用的 xList yList ,并且值可以直接从 varX varY <派生/ em>下降。

  3. 最后,将canvas移动到要调用一次的__init__方法,而不是每次都创建一个新画布。

  4. 以下是 Home 类的调整:

    class Home(tk.Frame):
    
        def __init__(self, parent, controller):
            self.controller = controller
            tk.Frame.__init__(self,parent)
            label = tk.Label(self, text="Start Page", font=LARGE_FONT)
            label.pack(pady=10, padx=10)
            canvas = FigureCanvasTkAgg(fig, self)
    
            def selectXY():
                x = varX.get()            
                y = varY.get()
    
                X.config(text=x)
                Y.config(text=y)
    
                ax.clear()
                df.plot.scatter(x, y, ax=ax)
    
                canvas.draw()
                canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
    
            # Y axis select
            varY = tk.StringVar(self)
            # initial value
            varY.set('Select Y axis')
    
            optionY = tk.OptionMenu(self, varY, *Options)
            optionY.pack()
    
            # X axis select
            varX = tk.StringVar(self)
            # initial value
            varX.set('Select X axis')
    
            optionX = tk.OptionMenu(self, varX, *Options)
            optionX.pack()
    
            button2 = tk.Button(self, text="Plot Axes", command = selectXY)
            button2.pack()
    
            button2 = ttk.Button(self, text="Graph",
                                 command=lambda: controller.show_frame(Graph))
            button2.pack()
    
            Y = ttk.Label(self, text=yList)
            Y.pack()
    
            X = ttk.Label(self, text=xList)
            X.pack()
    

    对于 Graph 类,要复制与 Home 相同的图,需要对全局变量, show_frame 中的visiblity触发事件和更新的属性进行一些广泛的调整在 Graph