tkinter 中嵌入的 matplotlib 不会在窗口关闭时退出主循环

问题描述 投票:0回答:1

我将代码归结为这个最小的可重现示例:

import matplotlib.pyplot as plt
from tkinter import Tk
from tkinter import Tk, Frame
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
   
Dates=["a","b","c","d"]
Numbers=[1,4,2,6]


def test():
    fig, ax = plt.subplots(figsize=(10,7))
    ax.plot(Dates, Numbers, linestyle='-', color='gray', alpha=0.5)
    root = Tk()
    root.title("Test")
    frame = Frame(root)
    frame.pack(fill='both', expand=True)
    canvas = FigureCanvasTkAgg(fig, master=frame)
    canvas.draw()
    canvas.get_tk_widget().pack(fill='both', expand=True)
    def f_test():
        print("HI")
    f_test()
    root.mainloop()
    
test()

我遇到的问题是,每当我调用该函数时,它就会开始运行但永远不会结束。即使我关闭 Tk 窗口,它仍会继续运行。我已经尝试过

'winfo_exists()'
但它就是行不通。

我在

'f_test'
里面有
'test()'
,因为我有2个函数只在
'test()'
内部使用,所以我在里面定义了它们。

python matplotlib tkinter
1个回答
1
投票

正如我在评论中怀疑的那样,这是由于阻塞 tkinter

mainloop
在您的情况下从未正确退出。

主循环是一个事件处理程序。这意味着它基本上是一个更新 GUI 的无限循环。所以一旦你输入了。您的代码中的所有内容将永远不会被访问。请参阅这篇文章以供参考。

按照来自 matplotlib.org 的 教程,我实现了一个关闭例程

_on_closing
来停止阻塞
mainloop
并正确销毁
Tk
实例。该例程由关闭 tkinter 窗口时的
WM_DELETE_WINDOW
事件触发。

import matplotlib.pyplot as plt
from tkinter import Tk, Frame
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

Dates = ["a", "b", "c", "d"]
Numbers = [1, 4, 2, 6]


def test():
    fig, ax = plt.subplots(figsize=(10, 7))
    ax.plot(Dates, Numbers, linestyle='-', color='gray', alpha=0.5)
    root = Tk()
    root.title("Test")
    frame = Frame(root)
    frame.pack(fill='both', expand=True)
    canvas = FigureCanvasTkAgg(fig, master=frame)
    canvas.draw()
    canvas.get_tk_widget().pack(fill='both', expand=True)

    def f_test():
        print("HI")

    def _on_closing():
        root.quit()  # stops mainloop
        root.destroy()  # this is necessary on Windows to prevent Fatal Python Error: PyEval_RestoreThread: NULL tstate

    root.protocol("WM_DELETE_WINDOW", _on_closing)  # bind closing routine
    f_test()
    root.mainloop()


test()

另请注意,当 tkinter 窗口打开时,

mainloop
正在运行,因此其余代码将被阻止,直到您关闭窗口!

© www.soinside.com 2019 - 2024. All rights reserved.