将matplotlib画布嵌入到tkinter GUI中 - 绘图没有显示,但没有抛出错误

时间:2017-03-04 18:37:57

标签: python matplotlib tkinter tkinter-canvas

下面运行python python脚本不会显示嵌入的matplotlib图。但是它也不会抛出任何错误消息。在运行脚本时,它应该显示一个GUI,左侧显示4个按钮,右侧显示实时图形。该图从文本文件'sample_graph_data.txt'接收其输入,该文件与脚本位于同一目录中。脚本有什么问题,我该如何使它工作?

#Script begins here
from tkinter import * 
from tkinter import messagebox
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import animation
from matplotlib import style
from matplotlib.figure import Figure
PROGRAM_NAME = 'Smart Farm Controller'
style.use('ggplot')

fig = Figure(figsize=(5, 30), dpi=100)
a = fig.add_subplot(111)

class Controller:

    def __init__(self, root):
        self.root = root
        self.root.title(PROGRAM_NAME)
        self.root.protocol('WM_DELETE_WINDOW', self.exit_app)
        self.init_gui()

    def create_right_graphs(self):
        right_frame = Frame(self.root)
        right_frame.grid(row=2, column=6, sticky=N+E+W+S,
                         padx=2, pady=2)
        anim = animation.FuncAnimation(fig, self.animate_graph(right_frame),
                                       interval=1000)

    def create_left_switches(self):
        left_frame = Frame(self.root)
        left_frame.grid(row=2, column=1, columnspan=6, sticky=N+E+W+S,
                        padx=2, pady=2)
        led_button = Button(left_frame, text='LED') #command=self.on_led_button_clicked)
        led_button.config(height=2, width=30)
        led_button.grid(row=2, column=0, padx=4, pady=8)
        apump_button = Button(left_frame, text='Air Pump') #command=self.on_apump_button_clicked)
        apump_button.config(height=2, width=30)
        apump_button.grid(row=3, column=0, padx=4, pady=8)
        wpump_res_button = Button(left_frame, text='Reservoir Water Pump')
                                    #command=self.on_wpump_res_button_clicked)
        wpump_res_button.config(height=2, width=30)
        wpump_res_button.grid(row=4, column=0, padx=4, pady=8)
        wpump_grow_button = Button(left_frame, text='Grow Bucket Water Pump')
                                    #command=self.on_wpump_grow_button_clicked)
        wpump_grow_button.config(height=2, width=30)
        wpump_grow_button.grid(row=5, column=0, padx=4, pady=8)

    def animate_graph(self, right_frame):
        pullData = open("sample_graph_data.txt","r").read()
        dataList = pullData.split('\n')
        xList = []
        yList = []
        for eachLine in dataList:
            if len(eachLine)>1:
                x, y = eachLine.split(',')
                xList.append(int(x))
                yList.append(int(x))

        a.clear()
        a.plot(xList, yList)
        canvas = FigureCanvasTkAgg(fig, right_frame)
        canvas.show()
        canvas.get_tk_widget().pack(side=RIGHT, fill=BOTH, expand=True)

    def init_gui(self):
        self.create_right_graphs()
        self.create_left_switches()

    def exit_app(self):
        if messagebox.askokcancel("Quit", "Really quit?"):
            self.root.destroy()


if __name__ == '__main__':
    root = Tk()
    Controller(root)
    root.mainloop()

1 个答案:

答案 0 :(得分:0)

在运行时,问题中的代码确实没有触发错误,但它也没有按预期运行。有些错误根本没有被触发,因为从不调用代码的相应部分 有几个问题:

  • 您需要将FigureCanvas实际添加到动画外的Frame
  • 始终保留对要处理的对象的引用。特别是动画必须活着。最好通过使用self使其成为类属性来完成。
  • 您需要将帧实际放置到根窗口。这可以使用pack
  • 完成
  • 在FuncAnimation中,您不能将函数调用为动画,而只是将其作为参数提供。此外,您需要提供一些帧来动画以启动动画。 FuncAnimation(fig, self.animate_graph, frames=12)代替 FuncAnimation(fig, self.animate_graph(someargument))
  • 动画函数需要一个参数,即framenumber(或frames参数给出的列表中的列表条目)。如果需要,您可以提供进一步的参数(在这种情况下参考文档)。

我确定我也忘了提及其他一些事情。但这是一个正在运行的代码。

from tkinter import * 
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import animation
from matplotlib import style
from matplotlib.figure import Figure
style.use('ggplot')

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

class Controller:

    def __init__(self, root):
        self.root = root
        self.create_left_switches()
        self.create_right_graphs()    

    def create_right_graphs(self):
        right_frame = Frame(self.root)
        right_frame.grid(row=2, column=6, sticky=N+E+W+S,
                         padx=2, pady=2)
        right_frame.pack(fill=X, padx=5, pady=5)
        self.canvas = FigureCanvasTkAgg(fig,right_frame ) 
        self.canvas.get_tk_widget().pack(side=RIGHT, fill=BOTH, expand=True)

        self.anim = animation.FuncAnimation(fig, self.animate_graph, frames=12,
                                       interval=500, repeat=True)
        self.canvas.show()

    def create_left_switches(self):
        left_frame = Frame(self.root)
        left_frame.grid(row=2, column=1, columnspan=6, sticky=N+E+W+S,
                        padx=2, pady=2)
        left_frame.pack(fill=X, padx=5, pady=5)
        led_button = Button(left_frame, text='LED') #command=self.on_led_button_clicked)
        led_button.config(height=2, width=30)
        led_button.grid(row=2, column=0, padx=4, pady=8)


    def animate_graph(self, i):
        pullData = open("sample_graph_data.txt","r").read()
        dataList = pullData.split('\n')
        xList = []
        yList = []
        for eachLine in dataList:
            if len(eachLine)>1:
                x, y = eachLine.split(',')
                xList.append(int(x))
                yList.append(int(y)**(1+i/12.))

        a.clear()
        a.plot(xList, yList)

if __name__ == '__main__':
    root = Tk()
    Controller(root)
    root.mainloop()