【问题标题】:Stuck in infinite loop after destroying parent window (python, Tkinter)破坏父窗口后陷入无限循环(python,Tkinter)
【发布时间】:2018-03-26 13:52:05
【问题描述】:

我遇到的问题是我似乎陷入了无限循环,(如果不是,请纠正我)。我在 Windows 10 上将 tkinter 用于 python 3.6(64 位)。

在模块中,我遇到了一个问题,我有 3 个条目小部件和 2 个按钮。两个按钮都调用“destroy()”函数来杀死父窗口。

下面是我的模块的高度抽象版本,模块的目的是从入口小部件中获取输入并将它们写入文件。

def Create():
    parent = Tk()
    parent.MakeItlookNice
    entry1 = Entry(parent)
    entry1.insert(INSERT, "Please enter your desired username here")
    entry2 = Entry(parent)
    entry2.insert(INSERT, "Please enter your desired password here")
    entry3 = Entry(parent)
    entry3.insert(INSERT, "What is your mother's maiden name")
    Submit = tk.Button(parent,
                       text ="Click here to submit your stuff",
                       command = lambda: [parent.destroy(),
                                          submit.function()])
    Cancel = tk.Button(parent,
                       text ="Click here to cancel your request",
                       command = lambda: parent.destroy())
    parent.mainloop()

此功能包含在“RegisterNewUser”模块中。 “菜单”模块是调用此函数的模块。据我所知,一旦调用了 parent.destroy(),就没有更多的代码可以执行,因为它都包含在 parent.mainloop() 中,因此该函数已完成,“菜单”模块应继续执行。

应该发生什么:

  1. 我希望提交按钮破坏窗口,执行功能,然后返回“菜单”模块。
  2. 我希望取消按钮破坏窗口并返回“菜单”模块。

实际发生了什么:

  1. 窗口按原样关闭
  2. 但是“菜单”模块内的代码没有再次开始执行
  3. 当我关闭 python shell 时,它警告我程序仍在运行

最后我的问题是,什么代码仍在运行,为什么它没有停止?

感谢您阅读本文,如果您需要更多详细信息,请告诉我。

编辑:在发布此问题之前,我已经对此主题进行了研究。我已经阅读了关于 tk.destroy() 函数和 tk.mainloop() 函数的文档,我还在 IDLE 中打开了 Tkinter 模块,以尝试更深入地了解发生了什么,但毕竟,我是仍然无法找出解决方案。这是我关于堆栈溢出的第一个问题,如果我做错了什么,请原谅我。

【问题讨论】:

  • 我认为当你关闭父级时,主循环正在运行。可能会出现窗口,但 python 仍在运行。
  • 嗨迈克尔,我认为 parent.destroy 会结束主循环中的所有进程。如果父窗口被销毁但主循环仍在运行,我该如何结束主循环。
  • 试试exit(0)。退出程序
  • 见下面我的回答;就我而言,你没有做错任何事
  • 不幸的是杀死了整个程序,我只想销毁父窗口并返回调用该函数的“菜单”模块

标签: python-3.x tkinter


【解决方案1】:

嗯,你说的是多个窗口?实现复杂 UI 的更简单方法是使用称为框架的概念。如果您切换到新框架,Tkinter 允许您完全更改屏幕和布局。这可能需要您重新编写大量代码。示例见Switch between two frames in tkinter 另外,有人在 youtube 上使用 tkinter 和框架构建了一个非常好的比特币监控应用程序

【讨论】:

  • 谢谢,我会调查一下,看看它是否能解决我的问题
  • 谢谢,对于复杂的 GUI,框架更容易使用
【解决方案2】:

我认为您可能会从这里使用Toplevel() 受益。

我已将您提供的代码添加到用于创建主窗口和管理弹出窗口的类中。

我注意到你的代码有一些问题。

很明显,您要像这样两次导入 tkinter:

import tkinter as tk
from tkinter import *

我可以从您编写输入字段与按钮的方式中看出。不要这样做。相反,只是使用了其中一种。我建议只使用import tkinter as tk

您正在使用一个函数来创建一个新的 tkinter 实例,并根据您的问题判断您已经准备好为您的菜单创建一个 tkinter 实例。除了创建新的 Tk() 实例之外,您还可以使用 Toplevel() 打开一个新窗口,该窗口可以继承主窗口的所有内容并且应该更易于管理。

在这种情况下,您实际上不需要使用 lambda。我还删除了 lambda 函数并替换为一个可以在这里工作的简单命令。

看看下面的代码,如果你有任何问题,请告诉我。

import tkinter as tk


class MyApp(tk.Frame):

    def __init__(self, master, *args, **kwargs):
        tk.Frame.__init__(self, master, *args, **kwargs)
        self.master = master
        self.master.title("Main MENU")

        tk.Button(self.master, text="Open top level", command = self.create).pack()


    def create(self):
        self.top = tk.Toplevel(self.master)
        entry1 = tk.Entry(self.top, width = 35)
        entry1.pack()
        entry1.insert(0, "Please enter your desired username here")
        entry2 = tk.Entry(self.top, width = 35)
        entry2.pack()
        entry2.insert(0, "Please enter your desired password here")
        entry3 = tk.Entry(self.top, width = 35)
        entry3.pack()
        entry3.insert(0, "What is your mother's maiden name")
        tk.Button(self.top, text ="Click here to submit your stuff",
                           command = self.Submit).pack()

        tk.Button(self.top, text ="Click here to cancel your request",
                           command = self.top.destroy).pack()

    def Submit(self):
        print("Do something here to submit data")
        self.top.destroy()

if __name__ == "__main__":
    root = tk.Tk() 
    app1 = MyApp(root)
    tk.mainloop()

【讨论】:

    【解决方案3】:

    您可以在您的mainloop() 之前(或代替)使用toplevel() 及其库函数wait_window(),您的问题将得到解决

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-13
      相关资源
      最近更新 更多