如果与matplotlib.pyplot

时间:2017-08-30 12:45:25

标签: python python-3.x matplotlib tkinter

我使用tkintermatplotlib.pyplot遇到了一个我不明白的问题。

最小的例子

import tkinter
import tkinter.filedialog as  tk_filedialog

import numpy as np
import matplotlib.pyplot as plt

def main():

    # # -- part 1 --
    # tkinter.Tk().withdraw()
    junk = tk_filedialog.askopenfilename()

    # # -- part 2 --
    x_p = np.linspace(0,10,100)
    fig = plt.figure()
    plt.plot(x_p,x_p,color='b')
    plt.show()

    print("blob")

if __name__ == '__main__':
    main()
print("blab")

我的实现最初是将行tkinter.Tk().withdraw()取消注释,但是后来你看不到会发生什么。

上述程序将运行但不会终止。它应该执行以下步骤:

  1. 打开Tkinter“选择文件对话框” - >选择任何文件,因为它什么都不做。
  2. 绘制曲线 - >关闭绘图窗口
  3. 打印“blob”,打印“blab”
  4. 问题是被tkinter.Tk().withdraw()抑制的Tkinter窗口不会关闭。这会导致两种意外行为 - 见下文。

    最令人困惑的部分是:如果您评论-- part 1 ---- part 2 --,程序将按预期运行。

    Winpython3.5从Cygwin

    开始

    关闭此tkinter窗口后,将打印“blob”和“blab”,程序将按预期终止。 enter image description here

    Spyder 3

    在关闭图形窗口之前和关闭tk窗口之前打印“blob”和“blab”。另外,关闭tk窗口是不可能的(x按钮什么都不做)。尽管如此,它还是关闭了spyder。 enter image description here

    IDLE

    与Cygwin相同的行为。

    有什么想法吗?我是否错过了tkinter的close()命令?

    我发现了这个:

    tk_window = tkinter.Tk()
    tk_window.destroy()
    

    但这并不能解决上述问题。

2 个答案:

答案 0 :(得分:2)

在原始代码中,您使用tkinter.Tk()显式创建了一个根窗口。像所有tkinter小部件类调用一样,这实际上创建了Python类的实例和 tk C结构。但是,不是将Python实例绑定到名称,以便稍后可以访问它,而是立即调用方法.withdraw()

在你的回答中,正确保留对root(传统名称,如self)的引用,这样你就可以在需要时销毁tk根结构而不是当程序退出时。

实际上,如果tkinter._support_default_root为真,默认情况下为,则Tk()实例绑定到tkinter._default_root。在原始代码中,您可以调用tkinter._default_root.destroy()。但我强烈建议您保留自己的参考,就像在答案中所做的那样。

在禁用对Tk()的显式调用后,为什么原始代码继续工作,并且创建了根?因为如果tkinter._support_default_root为真,那么tkinter会为您运行_default_root = Tk(),作为一种便利,'}特征。但是,如果您希望隐藏的默认根在该过程的持续时间内保持不变,这将非常方便。

重复:你在答案中所做的是使用tkinter的标准,记录,正确的方式。

答案 1 :(得分:1)

经过大量的反复试验,我找到了解决方案。以下代码段替换了我的问题中的第一部分代码。

    [...]
    # # -- part 1 --

    root = tkinter.Tk()
    # root.withdraw()
    cwd = os.getcwd()
    junk = tk_filedialog.askopenfilename()
    root.destroy()

    # # -- part 2 --
    [...]

似乎askopenfilename()打开了tkinter的根窗口,但是不确保在执行该行之后它被关闭/销毁。