I am new to tkinter and I was wondering if there is a way to clear whole root (window). I tried with root.destroy() , but I want to have a chance to undo(to callback some widgets). I also tried .pack_forget() and .grid_forget() , but it takes a lot of time and later may cause many bugs in program.
Thank you for help.
If you plan on literally destroying everything in the root window, my recommendation is to make a single frame be a child of the root window, and then put everything inside that frame. Then, when you need to clear the root window you only have to delete this one widget, and it will take care of deleting all of the other widgets.
If instead of destroying the widgets you want to merely hide them, the best solution is to use grid, so that you can use grid_forget to remove them from view, and grid to make them visible again. You can use pack and pack_forget, but pack doesn't remember where the widget was, making it more difficult to restore them without a lot of work.
If your program is made of logical groups of widgets, use frames to create the groups, and then you can destroy or call grid_forget on the entire frame at once, rather than having to do that for each individual widget.
for ele in root.winfo_children():
ele.destroy()
Related
def change_section_to_main():
SUB_SECTION.destroy()
APP_MAIN_FRAME.pack()
I want to restore the widget "APP_MAIN_FRAME". I thought I could do it with pack() turns out I was wrong. I keep getting this Error >>
_tkinter.TclError: bad window path name ".!frame
You can't "undestroy" a widget. Once it has been destroyed it can no longer be used.
Usually, the solution to this specific problem is to hide the widget rather than destroy it. You can hide it by using one of pack_forget, grid_forget, grid_remove or place_forget depending on exactly what you want to have happen and on which tool (pack, grid, or place) that you used to add it to the window.
If you expect to hide and show a widget often, grid is the best choice since grid_remove will remember how the item was placed. A subsequent call to grid() with no arguments will restore all of the settings. pack and place do not remember the configuration of a widget when it is forgotten.
if bool(suggestion_label.winfo_ismapped()):
suggestion_label.destroy()
else:
suggestion_label.pack()
I wanted to ask that anything i do the label packs on the screen and its not deleted second time PART of the code runs.
If you call destroy on a widget, it's gone and can't be used again.
If you want to hide and reveal it, use pack_forget instead of destroy. Be aware that pack is dependent on the order it's called. Re-packing the widget may not put it back in the same place unless you explicitly use the before or after options.
If you use grid, it has a grid_remove function where it will remember where it was replaced. Calling grid with no arguments will restore it with the same grid settings.
I just want the equivalent of closing and reopening my main program. I want to invoke it when a "new"-like option from a drop-down menu is clicked on. Something like calling root.destroy() and then re-initiating the mainloop.
How can I get this done?
There are at least three ways you can solve this.
Method one: the head fake. When you create your app, don't put all the widgets in the root window. Instead, hide the root window and create a new toplevel that represents your application. When you restart it's just a matter of destroying that new toplevel and re-running all your start-up logic.
Method two: nuke and pave. Similar in concept but slightly different in execution. In this model, when you want to restart you simply delete all the widgets in the main window, reset the geometry to null (so the window will once again resize itself based on its contents) and then run the logic that draws all the other widgets.
Method three: if it worked the first time... As suggested by Martin v. Löwis, simply have your program exec a new instance of the program, then exit.
The first two methods are potentially faster and have the (dis?)advantage of preserving the current environment. For example you could save the copy of the clipboard, column widths, etc. The third method absolutely guarantees a blank slate.
If you are on Unix, restart the entire application with os.execv. Make sure you pass all command line arguments etc.
You could take all your GUI building logic and initial state code out of the mainloop and put it into functions. Call these functions from the mainloop (something like: buildgui() & initstate()) and then, when the user clicks your menu icon, just call initstate() to set it back like it was when the application first started.
I know that I can subclass a tk.Frame (or ttk.Frame) and add that to a TopLevel to make secondary windows, but I'm not sure how I should use that as the main window. I know that creating an instance of a Frame class and calling .mainloop() on it seems to work for using it as the main window, but I feel like that's bad practice...
What do other people do when they are making GUI layouts that they want to have available to main windows and secondary windows?
Create a subclass of a Frame, and then put it either in the root window or a toplevel. In either case, you still call mainloop only once on the root window.
The only care you have to take is that you have to be careful about letting the user close the root window, because it will cause all of the other windows to be destroyed.
If you're creating a program that can have multiple windows, you might want to consider hiding the root window and always putting your window in a Toplevel. Of course, when you do that you need to make sure you destroy the root window whenever the last toplevel window is destroyed, or your program will continue to run but the user will have no way to access it.
Do you mean having a home screen that you can flip back to? If so, you can try looking here: Using buttons in Tkinter to navigate to different pages of the application?
I just want the equivalent of closing and reopening my main program. I want to invoke it when a "new"-like option from a drop-down menu is clicked on. Something like calling root.destroy() and then re-initiating the mainloop.
How can I get this done?
There are at least three ways you can solve this.
Method one: the head fake. When you create your app, don't put all the widgets in the root window. Instead, hide the root window and create a new toplevel that represents your application. When you restart it's just a matter of destroying that new toplevel and re-running all your start-up logic.
Method two: nuke and pave. Similar in concept but slightly different in execution. In this model, when you want to restart you simply delete all the widgets in the main window, reset the geometry to null (so the window will once again resize itself based on its contents) and then run the logic that draws all the other widgets.
Method three: if it worked the first time... As suggested by Martin v. Löwis, simply have your program exec a new instance of the program, then exit.
The first two methods are potentially faster and have the (dis?)advantage of preserving the current environment. For example you could save the copy of the clipboard, column widths, etc. The third method absolutely guarantees a blank slate.
If you are on Unix, restart the entire application with os.execv. Make sure you pass all command line arguments etc.
You could take all your GUI building logic and initial state code out of the mainloop and put it into functions. Call these functions from the mainloop (something like: buildgui() & initstate()) and then, when the user clicks your menu icon, just call initstate() to set it back like it was when the application first started.