Reputation:
I am trying to make a kind of GUI with tkinter, and here is the code. But, when I run it, click settings, and then back, python crashes. 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,
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)
Upvotes: 0
Views: 1226
Reputation: 21453
If your program represents one application, only make one Tk
instance.
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.
Instead of using Tk
as separate windows use Toplevel
as that is what they are intended for, separate windows.
By replacing all occurences of tk.Tk()
in your program with tk.Toplevel(abs_root)
then defining abs_root
as tk.Tk()
like this:
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. (not possible with your program as it is written)
Upvotes: 1