【问题标题】:Embedding matplotlib canvas into tkinter GUI - plot is not showing up, but no error is thrown将 matplotlib 画布嵌入 tkinter GUI - 绘图未显示,但未引发错误
【发布时间】:2017-07-24 19:12:51
【问题描述】:

运行下面的 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()

【问题讨论】:

  • 尝试创建一个较小的 Tkinter 应用程序的minimal reproducible example,看看你是否可以运行它
  • 我看到了几个应该引发错误的问题。尝试从终端运行它,以便查看错误。如果您仍然需要帮助,请提供我们可以尝试的完整示例(包括测试数据)。对于多个文件,最好创建一个 github 存储库并在此处发布链接。

标签: python matplotlib tkinter tkinter-canvas


【解决方案1】:

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

  • 您需要在动画外实际将FigureCanvas 添加到Frame
  • 始终保留对您要处理的对象的引用。尤其是动画必须保持活力。最好通过使用self 将其设为类属性来完成。
  • 您需要将框架实际放置到根窗口。这可以使用pack 来完成。
  • 在 FuncAnimation 中,您不能调用该函数来制作动画,而只需将其作为参数提供。此外,您需要提供一些帧来制作动画以启动动画。 FuncAnimation(fig, self.animate_graph, frames=12) 而不是 FuncAnimation(fig, self.animate_graph(someargument))
  • 动画函数需要一个参数,它是帧号(或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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    相关资源
    最近更新 更多