【发布时间】: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()