简体   繁体   English

Tkinter destroy方法使程序崩溃

[英]Tkinter destroy method crashes the program

I am trying to make a kind of GUI with tkinter, and here is the code. 我正在尝试使用tkinter制作一种GUI,这是代码。 But, when I run it, click settings, and then back, python crashes. 但是,当我运行它时,单击设置,然后返回,python崩溃。 Do you have any idea why this might happen and how I would fix it? 您是否知道为什么会发生这种情况以及我将如何解决? It happens when either I run the destroy function, or when I do something in the other Tk window, 当我运行destroy函数或在其他Tk窗口中执行某项操作时,就会发生这种情况

The code: (some might not be necessary, but I will include it) 代码:(可能没有必要,但我会包括在内)

import tkinter as tk

class moveFrame():
    def move(self, event):
        widget = event.widget
        widget.place(x = widget.winfo_x() + event.x - widget.startX, y = widget.winfo_y() + event.y - widget.startY)

def resize(self, event):
    widget = event.widget
    wlength = widget["length"]
    wwidth = widget["width"]
    widget.config(length = wlength + event.x - widget.startX, width = wwidth + event.y - widget.startY)

def getPos(self, event):
    widget = event.widget
    widget.lift()
    widget.startX, widget.startY = event.x, event.y

def __init__(self, master, frameInfo, xPos, yPos):
    self.frame = tk.Frame(master, cnf = frameInfo)
    self.frame.bind("<Button-1>", self.getPos)
    self.frame.bind("<B1-Motion>", self.move)
    self.frame.bind("<B3-Motion>", self.getPos)
    self.frame.bind("<Button-3>", self.resize)
    self.frame.place(x = xPos, y = yPos)


def homescreen():
    screen = tk.Tk()
    #arrangeButton = tk.Canvas(screen, width = 120, height = 40, bg = "purple")
    #arrangeButton.create_text(60, 20, text = "Arrange Homescreen")
    #arrangeButton.place(x = 0, y = 0)
    #arrangeButton.bind("<Button-1>", lambda event: arrange(arrangeButton))
    settingsButton = tk.Canvas(screen, width = 60, height = 60)
    settingsButton.place(x = 20, y = 20)
    settingsButton.create_oval(5, 5, 58, 58, fill = "#a6a6a6", tags = "click")
    settingsButton.create_oval(15, 10, 58, 53, fill = "#000", tags = "click")
    settingsButton.create_oval(27, 22, 46, 41, fill = "#00f", tags = "click")
    settingsButton.tag_bind("click", "<Button-1>", lambda event: settings())

def settings():
    sscreen = tk.Tk()
    #Get previous settings
    try:
        file = open("settings.txt", "r")
    except IOError:
        file = open("settings.txt", "x")
    finally:
        file = open("settings.txt", "r+")
    curSet = [x.strip("\n") for x in file.readlines()]
    #Widgets
    back = tk.Canvas(sscreen, width = 60, height = 48)
    back.place(x = 20, y = 20)
    back.create_rectangle(25, 22, 60, 26, fill = "#000", tags = "sclick")
    back.create_polygon(10, 24, 25, 10, 25, 38, fill = "#000", tags = "sclick")
    back.create_text(42, 32, text = "Back", tags = "sclick")
    back.tag_bind("sclick", "<Button-1>", lambda event: sscreen.destroy())

def arrange(*widgets):
    arrangeScreen = tk.Tk()
    arrangeButton = widgets[0]
    aBaF = moveFrame(arrangeScreen, {"bd" : 4, "bg" : "#a6a6a6"}, arrangeButton.winfo_x() - 4, arrangeButton.winfo_y() - 4)
    aBa = tk.Canvas(aBaF, width = 120, height = 40, bg = "purple")


def load(goTo, ms):
    load = tk.Tk()
    loadImage = tk.Canvas(load, height = 300, width = 300, bg = "black")
    loadImage.pack()
    loadImage.create_oval(125, 130, 175, 180, fill = "white")
    loadImage.create_oval(130, 140, 170, 150, fill = "black")
    loadImage.create_oval(130, 140, 171, 151, fill = "white")
    loadImage.create_oval(152, 140, 148, 150, fill = "black")
    load.after(ms, lambda: [goTo(), load.destroy()])

load(homescreen, 1)

If your program represents one application, only make one Tk instance. 如果程序代表一个应用程序,则仅创建一个Tk实例。

The Tk object represents the root of the entire application, by deleting it and creating another one you are essentially creating a separate application and any references to the previously application results in undefined behaviour such as crashing python. Tk对象代表整个应用程序的根,通过删除它并创建另一个应用程序,您实际上是在创建一个单独的应用程序,对先前应用程序的任何引用都会导致未定义的行为,例如python崩溃。

Instead of using Tk as separate windows use Toplevel as that is what they are intended for, separate windows. 不要将Tk用作单独的窗口,而Toplevel用作单独的窗口,因为这是它们的目标。

By replacing all occurences of tk.Tk() in your program with tk.Toplevel(abs_root) then defining abs_root as tk.Tk() like this: 通过用tk.Toplevel(abs_root)替换程序中所有出现的tk.Tk() ,然后将abs_root定义为tk.Tk()如下所示:

abs_root = tk.Tk()
abs_root.withdraw() #hides the window while your program runs.
load(homescreen, 1)
abs_root.mainloop()

Will make your program work, however it does mean that it will run until abs_root is destroyed which cannot happen by clicking the close button since it is not shown as a window, you will either have to use some condition where you explicitly call abs_root.destroy() or choose one window that will be the first created and last to be closed and use that as the abs_root instead. 将使您的程序正常工作,但这确实意味着它将一直运行到abs_root被销毁为止(由于未将其显示为窗口,因此无法通过单击关闭按钮来完成该操作),您将不得不使用某些条件来明确调用abs_root.destroy()或选择一个将首先创建并最后关闭的窗口,并将其用作abs_root (not possible with your program as it is written) (由于您编写的程序无法使用)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM