import tkinter
import tkinter as tk
from tkinter import *
import turtle
from turtle import *
wn = turtle.Screen()
t = turtle.Turtle()
root = Tk()
root.title("control board")
turtle.title("drawing board")
root["bg"] = "black"
wn.bgcolor("black")
t.color("white")
root2 = tk.Toplevel(root)
root2.withdraw()
root3 = tk.Toplevel(root)
root3.withdraw()
root4 = tk.Toplevel(root)
root4.withdraw()
def circle():
t.circle(50)
def line():
b7.pack()
b8.pack()
b9.pack()
b2.forget()
def l_line():
t.left(30)
def r_line():
t.right(30)
def check():
b5.config(text = "u sure?", command = doublecheck)
def doublecheck():
turtle.bye()
root.destroy()
def sf():
t.forward(10)
def bf():
t.forward(50)
def hidef():
b7.forget()
b8.forget()
b9.forget()
b19.forget()
b2.pack()
b19.pack()
def colors():
root3.deiconify
root3.title("theme window")
b11 = Button(root3, height=2,
width=20,
bg="BLUE", fg="white",
text="blue",
command=bluec, )
b12 = Button(root3, height=2,
width=20,
bg="red", fg="white",
text="red",
command=redc, )
b13 = Button(root3, height=2,
width=20,
bg="yellow", fg="white",
text="yellow",
command=yellowc, )
b22 = Button(root3, height=2,
width=20,
bg="black", fg="yellow",
text="close color window",
command=root3.destroy, )
b11.pack()
b12.pack()
b13.pack()
b22.pack()
def bluec():
t.color("blue")
def redc():
t.color("red")
def yellowc():
t.color("yellow")
def undo():
t.undo()
def themes():
root2.deiconify()
root2.title("theme window")
b16 = Button(root2, height=2,
width=20,
bg="yellow", fg="blue",
text="hannukah theme",
command=htheme, )
b17 = Button(root2, height=2,
width=20,
bg="white", fg="red",
text="christmas theme",
command=ctheme, )
b22 = Button(root2, height=2,
width=20,
bg="white", fg="red",
text="customize themes",
command=customthemehub)
b18 = Button(root2, height=2,
width=20,
bg="black", fg="yellow",
text="close theme window",
command= root2.destroy, )
b16.pack()
b17.pack()
b22.pack()
b18.pack()
def htheme():
wn.bgcolor("yellow")
t.color("blue")
root["bg"] = "yellow"
b1["bg"] = "blue"
b2["bg"] = "blue"
b3["bg"] = "blue"
b4["bg"] = "blue"
b5["bg"] = "blue"
b7["bg"] = "blue"
b8["bg"] = "blue"
b9["bg"] = "blue"
b14["bg"] = "blue"
b15["bg"] = "blue"
b1["fg"] = "yellow"
b2["fg"] = "yellow"
b3["fg"] = "yellow"
b4["fg"] = "yellow"
b5["fg"] = "yellow"
b7["fg"] = "yellow"
b8["fg"] = "yellow"
b9["fg"] = "yellow"
b14["fg"] = "yellow"
b15["fg"] = "yellow"
def ctheme():
wn.bgcolor("red")
t.color("white")
root["bg"] = "red"
b1["bg"] = "white"
b2["bg"] = "white"
b3["bg"] = "white"
b4["bg"] = "white"
b5["bg"] = "white"
b7["bg"] = "white"
b8["bg"] = "white"
b9["bg"] = "white"
b14["bg"] = "white"
b15["bg"] = "white"
b1["fg"] = "red"
b2["fg"] = "red"
b3["fg"] = "red"
b4["fg"] = "red"
b5["fg"] = "red"
b7["fg"] = "red"
b8["fg"] = "red"
b9["fg"] = "red"
b14["fg"] = "red"
b15["fg"] = "red"
def penswitch():
b20.pack(side = tkinter.BOTTOM)
b21.pack(side = tkinter.BOTTOM)
b19.forget()
def penu():
t.penup()
b20.forget()
b21.forget()
b19.pack(side = tkinter.TOP)
def pend():
t.pendown()
b20.forget()
b21.forget()
b19.pack()
def customthemehub():
root4.deiconify()
b23 = Button(root4, height=2,
width=20,
bg="black", fg="blue",
text="select background color",
command=bgselect, )
b10 = Button(root4, height=2,
width=20,
bg="black", fg="white",
text="select drawing color",
command=colors )
b10.pack()
b23.pack()
def bluebg():
wn.bgcolor("blue")
def yellowbg():
wn.bgcolor("yellow")
root5 = tk.Toplevel(root)
b24 = Button(root5, height=2,
width=20,
bg="blue", fg="white",
text="blue background",
command=bluebg)
b25 = Button(root5, height=2,
width=20,
bg="yellow", fg="white",
text="yellow background",
command=yellowbg)
b24.pack()
b25.pack()
root5.withdraw()
def bgselect():
root4.withdraw()
root5.deiconify()
b1 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="circle",
command=circle,)
b2 = Button(root, height = 2,
width = 20,
bg = "black", fg = "white",
text="line",
command=line,)
b3 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text=" turn left",
command= l_line ,)
b4 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text=" turn right",
command= r_line ,)
b5 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text=" exit",
command= check ,)
b7 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="10 steps",
command= sf,)
b8 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="50 steps",
command= bf,)
b9 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="hide",
command= hidef,)
b14 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="undo last action",
command= undo,)
b15 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="select different themes",
command= themes,)
b19 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="pen up/down",
command= penswitch,)
b20 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="pen up",
command= penu,)
b21 = Button(root, height = 2,
width = 20,
bg="black", fg="white",
text="pen down",
command= pend,)
b15.pack()
b14.pack()
b5.pack(side = tkinter.LEFT, )
b4.pack()
b3.pack()
b1.pack()
b2.pack()
b19.pack()
root.mainloop()
sorry for the annoying code i know its a complete mess, basically the problem is with def: bgselecr and the choosing color, if anyone can run this code the click on the custom themes then customize theme then choose background color, when i close it and reopen the tab of the background color it "duplicates" the buttons i use the withdraw and deiconify method, if u need i can re-explain what i mean i have no idea what causes it, any help would be aprecitaed
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\PELEG\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\PELEG\PycharmProjects\idk\main.py", line 232, in bgselect
root5.deiconify()
File "C:\Users\PELEG\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 2013, in wm_deiconify
return self.tk.call('wm', 'deiconify', self._w)
_tkinter.TclError: bad window path name ".!toplevel5"
these are the errors after the code
CodePudding user response:
So the problem with your code here is that for any window(Toplevel
) that you have initialized, you initially withdraw
it but whenever you deiconify
it again, you pack two new buttons to it.
So for example lets take the background color selection window, the first time you run the function bgselect()
, it packs two buttons of the two colors to select from into the window. Now when you close the window, in reality the window along with the two buttons still exists and just has been withdrawn.
This means that the next time you deiconify
it, the old two packed buttons will still be there and there is no need to pack two new buttons to it again.
Now, the solution to this problem is to add these buttons when you initialize the Toplevel
widgets.
When going through your code it seems like all the Toplevel
widgets have been configured in the manner which leads to repeated packing of new buttons.
By removing the packing code from the functions and relocating it to the lines where all the Toplevel
s are initialized, the problem gets solved!
For example for root5
it will look like this after the fix -:
def bluebg():
wn.bgcolor("blue")
def yellowbg():
wn.bgcolor("yellow")
root5 = tk.Toplevel(root)
# Buttons are initialized once.
b24 = Button(root5, height=2,
width=20,
bg="blue", fg="white",
text="blue background",
command=bluebg)
b25 = Button(root5, height=2,
width=20,
bg="yellow", fg="white",
text="yellow background",
command=yellowbg)
b24.pack()
b25.pack()
root5.withdraw()
def bgselect():
root4.withdraw()
root5.deiconify()
# Buttons are no longer repeatedly initialized.
EDIT: As informed by you in comments, after making the changes suggested above, you run into the following error-:
Exception in Tkinter callback Traceback (most recent call last):
File "C:\Users\PELEG\AppData\Local\Programs\Python\Python39\lib\tkinter_init_.py", line 1892, in call return self.func(*args) File "C:\Users\PELEG\PycharmProjects\idk\main.py", line 232, in bgselect root5.deiconify() File "C:\Users\PELEG\AppData\Local\Programs\Python\Python39\lib\tkinter_init_.py", line 2013, in wm_deiconify return self.tk.call('wm', 'deiconify', self._w) _tkinter.TclError: bad window path name ".!toplevel5"
The error above occurs as the root5 and other Toplevel
windows are destroyed when they close rather than being withdrawn, and when you open them you deiconify them, but they already have been destroyed, so it throws an error.
The same can be fixed by calling the withdraw function on all Toplevel
s by binding it to their 'WM_DELETE_WINDOW'
protocol, which will trigger when window close button is pressed.
Like so-:
root5 = tk.Toplevel(root)
# Buttons are initialized once.
b24 = Button(root5, height=2,
width=20,
bg="blue", fg="white",
text="blue background",
command=bluebg)
b25 = Button(root5, height=2,
width=20,
bg="yellow", fg="white",
text="yellow background",
command=yellowbg)
b24.pack()
b25.pack()
root5.withdraw()
root5.protocol("WM_DELETE_WINDOW", root5.withdraw) # Binds the protocol to the callback
Now the same line has to be added in the initialization of all Toplevel
s.
This fixes the error.