简体   繁体   中英

tkinter: Why aren't Combobox and Entry widgets deleted by delete("all")?

I mean the whole widget not the text inside. I also tried to get an existing solution on the forum. I have stripped code to show the problem only.

My problem is... When I place ComboBox and Entry widgets on canvas2 , they don't get deleted with a canvas2.delete("all") .

The problem happens if you select "Weighted Graph", then "Undirected Graph" from the menu. After "Weighted Graph", the ComboBox and Entry widgets remain (everything else gets deleted as expected). I put in a time delay and some prompts to show the problem.

from tkinter import *
from tkinter import ttk
import time

tk = Tk()
tk.geometry("970x660")
menubar = Menu(tk)
tk.config(menu=menubar)

wrapper1 = LabelFrame(tk, text="Display", height=500)
wrapper2 = LabelFrame(tk, text="Command", width=800)

# canvas was setup to be a vertically scrolling region, I have cut most of that code
# (but my problem does not lie with canvas, that's working fine)
canvas = Canvas(wrapper1, height=500)
canvas.pack(side=LEFT, fill="both", expand="yes")

myframe = Frame(canvas)
canvas.create_window((0,0), window=myframe, anchor="nw", height=500)

# Note: My problem lies on canvas2,
canvas2 = Canvas(wrapper2)
canvas2.pack(side=LEFT, fill="both", expand="yes")

canvas2.update()

wrapper1.pack(fill="both", expand="yes", padx=10, pady=0)
wrapper2.pack(fill="both", expand="yes", padx=10, pady=5)

def DoNothing():
    print("Doing nothing!")

def BinaryTree(Weighted, Mode):

    canvas.delete("all")
    print("Before canvas2.delete...")
    canvas2.delete("all")
    print("...after canvas2.delete... now waiting 3 seconds so you can inspect if canvas2 is CLEAR... ")
    print("...I would expect canvas2 to be clear but Combobox and Entry remain!... ")

    canvas2.update()
    tk.update()

    time.sleep(3)

    button1 = Button(canvas2, text = "Add Node",  command= lambda: DoNothing(), width=13, anchor=W)
    button1_window = canvas2.create_window(20, 40, anchor=W, window=button1)

    entry1 = Entry(canvas2, width=10)
    entry1.place(x=150, y=40, anchor=W)

    button2 = Button(canvas2, text = "Add Edge",  command= lambda: DoNothing(), width=13, anchor=W)
    button2_window = canvas2.create_window(20, 80, anchor=W, window=button2)

    cb1 = ttk.Combobox(canvas2, values=DoNothing(), postcommand=lambda: DoNothing(), width=13, state="readonly")
    cb1.place(x=150, y=80, anchor=W)

    cb2 = ttk.Combobox(canvas2, values=DoNothing(), postcommand=lambda: DoNothing(), width=13, state="readonly")
    cb2.place(x=260, y=80, anchor=W)

    if Weighted == True:
        canvas2.create_text(380, 80, text="Weight:", anchor=W)
        entry2 = Entry(canvas2, width=4)
        entry2.place(x=429, y=80, anchor=W)

    button3 = Button(canvas2, text = "Delete All Nodes",  command= lambda: DoNothing(), width=13, anchor=W)
    button3_window = canvas2.create_window(420, 40, anchor=W, window=button3)

    canvas2.update()
    tk.update()

lmenu = Menu(menubar)
menubar.add_cascade(label="Learning Menu", menu=lmenu)

lmenu.add_command(label="Weighted Graph", command= lambda: BinaryTree(True, "DirectedGraph"))
lmenu.add_command(label="Undirected Graph", command= lambda: BinaryTree(False, "UndirectedGraph"))


while True:
    tk.update_idletasks()
    tk.update()
    time.sleep(0.01)

Why aren't Combobox and Entry widgets deleted by delete(“all”)?

That's just how tkinter is designed to work. The canvas delete method only deletes canvas objects. That means, objects created on the canvas with the "create" functions ( create_rectangle , create_window , etc). For window objects, the delete method will delete the canvas object created with create_window but it's not designed to delete the widget associated with that window object.

Like with any widget, to delete the actual widget you need to call the destroy method on the widget itself.

My problem is... When I place ComboBox and Entry widgets on canvas2, they don't get deleted with a canvas2.delete("all").

That is because when you use place , you are not creating canvas objects. For the delete command to work, you must call create_window for the combox and entry widgets.

To destroy a widget in tkinter try.destroy()

f1=tk.Frame()
f1.destroy()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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