【问题标题】:tkinter freezes when "destroyed" from an open python session当从打开的 python 会话中“销毁”时,tkinter 冻结
【发布时间】:2020-12-03 17:11:00
【问题描述】:

问题:tkinter 的root.destroy() 函数因为我程序中的最后一行code.interact(local=locals()) 而冻结

BACKGROUND:我正在从终端运行我的程序。它会生成一些文本数据,使用所述数据创建一个类的实例,然后将我放到 python 会话中,然后我可以在其中运行方法并测试所有内容。通过code.interact(local=locals())

可以实现此口译员会话

从这里,我运行一个“编辑”方法,允许用户在 tkinter 文本框中编辑生成的文本,然后按下按钮保存并退出。该按钮调用一个函数来保存一个新的 txt 文件,然后使用root.destroy() 来结束 tkinter 主循环。但是,这会冻结并且实际上并没有关闭窗口。 删除最后的 code.interact 行并从程序本身(即不是从解释器)调用“编辑”方法可以解决问题。

在我的故障排除中,我发现 tkinter 在从 python 解释器调用时并不总是能正常运行,code.interact 确实如此。

问题:有没有办法在 python 解释器中保留 tkinter 功能?这实际上是我的问题,还是更多地与code.interact有关?

更新: 问题似乎与 tkinter 的 mainloop 与 code.interact 自己的循环一起运行有关。两个无限循环相互竞争。删除任一行似乎可以解决问题。在这种情况下,我的 GUI 不需要 mainloop,因为它不需要以交互方式更新其外观。

下面的示例代码(然后从后面的 python 解释器运行project_instance.edit()

import tkinter as tk
import code

class Project():
    def __init__(self, text):
        self.script = text

    def edit(self):
        root = tk.Tk()
        S = tk.Scrollbar(root)
        T = tk.Text(root, height=60, width=60, undo=True, insertbackground="white", wrap=tk.WORD, font=("Courier", 30), background="black", foreground="grey")
        S.pack(side=tk.RIGHT, fill=tk.Y)
        T.pack(side=tk.LEFT, fill=tk.Y)
        S.config(command=T.yview)
        T.config(yscrollcommand=S.set)
        quote = self.script
        T.insert(tk.END, quote)

        def file_save():
            text2save = str(T.get(1.0, tk.END)).strip() # starts from `1.0`, not `0.0`
            with open("script_text.txt", "w") as s:
                s.write(text2save)
                uri = s.name
            root.destroy()
        b = tk.Button(root, height=5, width=10, font=("Courier", 44), text="Save", command=file_save, background="black", foreground="grey").pack()
        root.mainloop()


sample_text = "This is sample text."
project_instance = Project(sample_text)
code.interact(local=locals())

【问题讨论】:

  • 代码是一个标准的python包。 docs.python.org/3/library/code.html 简单地说,在从终端调用你的 python 程序后,它会在 python 会话中“让你离开”。这当然是问题的一部分。
  • 好的……那么请提供一个可运行的minimal reproducible example
  • @martineau 刚刚添加了一些示例代码,感谢您的帮助
  • file_save() 函数中调用root.destroy() 会破坏root 及其所有子对象。您应该能够使用root.quit() 更优雅地退出mainloop()
  • @martineau 其实我很想知道quit()destroy()方法有什么区别,有时候quit()不能正常工作,所以我用destroy()

标签: python tkinter


【解决方案1】:

更新:问题似乎与 tkinter 的主循环与 code.interact 自己的循环一起运行有关。两个无限循环相互竞争。删除任一行似乎可以解决问题。在这种情况下,我的 GUI 不需要 mainloop,因为它不需要以交互方式更新其外观。

另一个修复方法是使用“after”方法销毁根。 root.after(1, root.destroy()) 似乎也能够“逃脱”竞争循环。

我想线程也可以将循环彼此隔离。本文中的更多好信息:

https://gordonlesti.com/use-tkinter-without-mainloop/#:~:text=The%20method%20mainloop%20has%20an,is%20waiting%20for%20some%20events.

【讨论】:

    猜你喜欢
    • 2011-10-18
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 2011-11-25
    相关资源
    最近更新 更多