difference between tk.Tk() and tk.Frame - python

I have noticed that both of the instructions tk.Tk() and tk.Frame make a new window, so what is the difference between them? and what is the advantage of using one over the other ?

I have noticed that both of the instructions tk.Tk() and tk.Frame make a new window
That is not correct. tk.Frame will not make a new window, except for the fact that any widget will force the creation of a root window if you haven't already created the root window.
Widgets in a tkinter application exist in a hierarchy, and that hierarchy must have a root window. The root window is special in that it doesn't have a parent. All other widgets must have a parent. Every application must have an instance of tk.Tk, and except for very rare circumstances you should never have more than one instance of tk.Tk.
tk.Frame is a frame: a widget with a border and not much else. Like all other widgets (except tk.Tk), it must have a parent.
The advantage to using tk.Tk is that your application must have an instance of it. If you don't create one, one will be created for you. The zen of python says explicit is better than implicit, so you should always explicitly create it.
The advantage to using tk.Frame is that it makes it easy to collect widgets into groups and be able to manage them as a group (add a border, lay them out as a group, etc).

Related

Tkinter drop down menu not showing selection [duplicate]

Consider below example:
import tkinter as tk
root = tk.Tk()
root.title("root")
other_window = tk.Tk()
other_window.title("other_window")
root.mainloop()
and also see below example that creates instances of Tk back-to-back instead of at once, so there's exactly one instance of Tk at any given time:
import tkinter as tk
def create_window(window_to_be_closed=None):
if window_to_be_closed:
window_to_be_closed.destroy()
window = tk.Tk()
tk.Button(window, text="Quit", command=lambda arg=window : create_window(arg)).pack()
window.mainloop()
create_window()
Why is it considered bad to have multiple instances of Tk?
Is the second snippet considered a bit better, or does it suffer from
the same conditions the first code does?
Why is it considered bad to have multiple instances of Tk?
Tkinter is just a python wrapper around an embedded Tcl interpreter that imports the Tk library. When you create a root window, you create an instance of a Tcl interpreter.
Each Tcl interpreter is an isolated sandbox. An object in one sandbox cannot interact with objects in another. The most common manifestation of that is that a StringVar created in one interpreter is not visible in another. The same goes for widgets -- you can't create widgets in one interpreter that has as a parent widget in another interpreter. Images are a third case: images created in one cannot be used in another.
From a technical standpoint, there's no reason why you can't have two instances of Tk at the same time. The recommendation against it is because there's rarely an actual need to have two or more distinct Tcl interpreters, and it causes problems that are hard for beginners to grasp.
Is the second snippet considered a bit better, or does it suffer from the same conditions the first code does?
It's impossible to say whether the second example in the question is better or not without knowing what you're trying to achieve. It probably is not any better since, again, there's rarely ever a time when you actually need two instances.
The best solution 99.9% of the time is to create exactly one instance of Tk that you use for the life of your program. If you need a second or subsequent window, create instances of Toplevel. Quite simply, that is how tkinter and the underlying Tcl/Tk interpreter was designed to be used.
I disagree with the tkinter community discouraging the use of multiple tk.Tk windows. You can have multiple tk.Tk windows. Using multiple instances of tk.Tk is the only way to create windows that are truly independent of each other. The only mistake most people make when creating multiple tk.Tk windows is that they forget to pass in master=... when creating PhotoImages/StringVars/IntVars/...
For example look at this code:
import tkinter as tk
root = tk.Tk()
root2 = tk.Tk()
variable = tk.StringVar() # Add `master=root2` to fix the problem
entry = tk.Entry(root2, textvariable=variable)
entry.bind("<Return>", lambda e: print(repr(variable.get())))
entry.pack()
root.mainloop()
The code above doesn't work. If you add master=root2 to the tk.StringVar(), then it will work perfectly fine. This is because tkinter stores the first instance of tk.Tk() in tk._default_root. Then if you don't pass in master=..., it will assume that you wanted the window in tk._default_root.
Another thing people get wrong is how many times should .mainloop() be called. It handles events from all tk.Tk windows that are alive so you only need one .mainloop().
For folks who disagree, I'd be interested in an example of where an actual problem is caused by the multiple tk.Tk windows.
The best reference I've found so far is the Application Windows section of the tkinterbook:
In the simple examples we’ve used this far, there’s only one window on the screen; the root window. This is automatically created when you call the Tk constructor
and
If you need to create additional windows, you can use the Toplevel widget. It simply creates a new window on the screen, a window that looks and behaves pretty much like the original root window
My take on it is that a Tk instance creates a Toplevel widget, plus things like the mainloop, of which there should be only one.
Tk() initializes the hidden tcl interpreter so that the code can run, as Tkinter is just a wrapper around tcl/tk. It also automatically creates a new window. Toplevel() just creates a new window, and wont work if Tk() hasn't been instantiated, as it requires the tcl interpreter that Tk() initializes. You cannot create any Tkinter widgets without instantiating Tk(), and Toplevel is merely a widget. In the question, you use Tk() to create a second window. You should instead create another file, because initializing the tcl interpreter multiple times can get confusing, as #Bryan Oakley explains so well. Then you should do:
from os import startfile
startfile(nameOfTheOtherFile)
, because, as Toplevel() is just a widget, it closes when the Tk() window is closed. Having the other window in a separate file makes it less confusing.

Python Tkinter Icon Not showing up [duplicate]

Consider below example:
import tkinter as tk
root = tk.Tk()
root.title("root")
other_window = tk.Tk()
other_window.title("other_window")
root.mainloop()
and also see below example that creates instances of Tk back-to-back instead of at once, so there's exactly one instance of Tk at any given time:
import tkinter as tk
def create_window(window_to_be_closed=None):
if window_to_be_closed:
window_to_be_closed.destroy()
window = tk.Tk()
tk.Button(window, text="Quit", command=lambda arg=window : create_window(arg)).pack()
window.mainloop()
create_window()
Why is it considered bad to have multiple instances of Tk?
Is the second snippet considered a bit better, or does it suffer from
the same conditions the first code does?
Why is it considered bad to have multiple instances of Tk?
Tkinter is just a python wrapper around an embedded Tcl interpreter that imports the Tk library. When you create a root window, you create an instance of a Tcl interpreter.
Each Tcl interpreter is an isolated sandbox. An object in one sandbox cannot interact with objects in another. The most common manifestation of that is that a StringVar created in one interpreter is not visible in another. The same goes for widgets -- you can't create widgets in one interpreter that has as a parent widget in another interpreter. Images are a third case: images created in one cannot be used in another.
From a technical standpoint, there's no reason why you can't have two instances of Tk at the same time. The recommendation against it is because there's rarely an actual need to have two or more distinct Tcl interpreters, and it causes problems that are hard for beginners to grasp.
Is the second snippet considered a bit better, or does it suffer from the same conditions the first code does?
It's impossible to say whether the second example in the question is better or not without knowing what you're trying to achieve. It probably is not any better since, again, there's rarely ever a time when you actually need two instances.
The best solution 99.9% of the time is to create exactly one instance of Tk that you use for the life of your program. If you need a second or subsequent window, create instances of Toplevel. Quite simply, that is how tkinter and the underlying Tcl/Tk interpreter was designed to be used.
I disagree with the tkinter community discouraging the use of multiple tk.Tk windows. You can have multiple tk.Tk windows. Using multiple instances of tk.Tk is the only way to create windows that are truly independent of each other. The only mistake most people make when creating multiple tk.Tk windows is that they forget to pass in master=... when creating PhotoImages/StringVars/IntVars/...
For example look at this code:
import tkinter as tk
root = tk.Tk()
root2 = tk.Tk()
variable = tk.StringVar() # Add `master=root2` to fix the problem
entry = tk.Entry(root2, textvariable=variable)
entry.bind("<Return>", lambda e: print(repr(variable.get())))
entry.pack()
root.mainloop()
The code above doesn't work. If you add master=root2 to the tk.StringVar(), then it will work perfectly fine. This is because tkinter stores the first instance of tk.Tk() in tk._default_root. Then if you don't pass in master=..., it will assume that you wanted the window in tk._default_root.
Another thing people get wrong is how many times should .mainloop() be called. It handles events from all tk.Tk windows that are alive so you only need one .mainloop().
For folks who disagree, I'd be interested in an example of where an actual problem is caused by the multiple tk.Tk windows.
The best reference I've found so far is the Application Windows section of the tkinterbook:
In the simple examples we’ve used this far, there’s only one window on the screen; the root window. This is automatically created when you call the Tk constructor
and
If you need to create additional windows, you can use the Toplevel widget. It simply creates a new window on the screen, a window that looks and behaves pretty much like the original root window
My take on it is that a Tk instance creates a Toplevel widget, plus things like the mainloop, of which there should be only one.
Tk() initializes the hidden tcl interpreter so that the code can run, as Tkinter is just a wrapper around tcl/tk. It also automatically creates a new window. Toplevel() just creates a new window, and wont work if Tk() hasn't been instantiated, as it requires the tcl interpreter that Tk() initializes. You cannot create any Tkinter widgets without instantiating Tk(), and Toplevel is merely a widget. In the question, you use Tk() to create a second window. You should instead create another file, because initializing the tcl interpreter multiple times can get confusing, as #Bryan Oakley explains so well. Then you should do:
from os import startfile
startfile(nameOfTheOtherFile)
, because, as Toplevel() is just a widget, it closes when the Tk() window is closed. Having the other window in a separate file makes it less confusing.

The checkbox does not pass its state to a variable [duplicate]

Consider below example:
import tkinter as tk
root = tk.Tk()
root.title("root")
other_window = tk.Tk()
other_window.title("other_window")
root.mainloop()
and also see below example that creates instances of Tk back-to-back instead of at once, so there's exactly one instance of Tk at any given time:
import tkinter as tk
def create_window(window_to_be_closed=None):
if window_to_be_closed:
window_to_be_closed.destroy()
window = tk.Tk()
tk.Button(window, text="Quit", command=lambda arg=window : create_window(arg)).pack()
window.mainloop()
create_window()
Why is it considered bad to have multiple instances of Tk?
Is the second snippet considered a bit better, or does it suffer from
the same conditions the first code does?
Why is it considered bad to have multiple instances of Tk?
Tkinter is just a python wrapper around an embedded Tcl interpreter that imports the Tk library. When you create a root window, you create an instance of a Tcl interpreter.
Each Tcl interpreter is an isolated sandbox. An object in one sandbox cannot interact with objects in another. The most common manifestation of that is that a StringVar created in one interpreter is not visible in another. The same goes for widgets -- you can't create widgets in one interpreter that has as a parent widget in another interpreter. Images are a third case: images created in one cannot be used in another.
From a technical standpoint, there's no reason why you can't have two instances of Tk at the same time. The recommendation against it is because there's rarely an actual need to have two or more distinct Tcl interpreters, and it causes problems that are hard for beginners to grasp.
Is the second snippet considered a bit better, or does it suffer from the same conditions the first code does?
It's impossible to say whether the second example in the question is better or not without knowing what you're trying to achieve. It probably is not any better since, again, there's rarely ever a time when you actually need two instances.
The best solution 99.9% of the time is to create exactly one instance of Tk that you use for the life of your program. If you need a second or subsequent window, create instances of Toplevel. Quite simply, that is how tkinter and the underlying Tcl/Tk interpreter was designed to be used.
I disagree with the tkinter community discouraging the use of multiple tk.Tk windows. You can have multiple tk.Tk windows. Using multiple instances of tk.Tk is the only way to create windows that are truly independent of each other. The only mistake most people make when creating multiple tk.Tk windows is that they forget to pass in master=... when creating PhotoImages/StringVars/IntVars/...
For example look at this code:
import tkinter as tk
root = tk.Tk()
root2 = tk.Tk()
variable = tk.StringVar() # Add `master=root2` to fix the problem
entry = tk.Entry(root2, textvariable=variable)
entry.bind("<Return>", lambda e: print(repr(variable.get())))
entry.pack()
root.mainloop()
The code above doesn't work. If you add master=root2 to the tk.StringVar(), then it will work perfectly fine. This is because tkinter stores the first instance of tk.Tk() in tk._default_root. Then if you don't pass in master=..., it will assume that you wanted the window in tk._default_root.
Another thing people get wrong is how many times should .mainloop() be called. It handles events from all tk.Tk windows that are alive so you only need one .mainloop().
For folks who disagree, I'd be interested in an example of where an actual problem is caused by the multiple tk.Tk windows.
The best reference I've found so far is the Application Windows section of the tkinterbook:
In the simple examples we’ve used this far, there’s only one window on the screen; the root window. This is automatically created when you call the Tk constructor
and
If you need to create additional windows, you can use the Toplevel widget. It simply creates a new window on the screen, a window that looks and behaves pretty much like the original root window
My take on it is that a Tk instance creates a Toplevel widget, plus things like the mainloop, of which there should be only one.
Tk() initializes the hidden tcl interpreter so that the code can run, as Tkinter is just a wrapper around tcl/tk. It also automatically creates a new window. Toplevel() just creates a new window, and wont work if Tk() hasn't been instantiated, as it requires the tcl interpreter that Tk() initializes. You cannot create any Tkinter widgets without instantiating Tk(), and Toplevel is merely a widget. In the question, you use Tk() to create a second window. You should instead create another file, because initializing the tcl interpreter multiple times can get confusing, as #Bryan Oakley explains so well. Then you should do:
from os import startfile
startfile(nameOfTheOtherFile)
, because, as Toplevel() is just a widget, it closes when the Tk() window is closed. Having the other window in a separate file makes it less confusing.

How should I make a class that can be used as my main app window, but also can be used as a secondary window

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?

GUI without WM frame

Is there a python library that allows you to create a GUI without the window manager (and equivalent under MS Windows) frame thing, and allow to set the window top-most (like over all other windows) ?
I've been looking on Internet but I'm obviously missing the right keywords.
Yup. Tkinter, or "tkinter" in python3. It's included in standard python distributions
Removing the Window Manager
The method
root.overrideredirect(True)
Removes the borders and manager. Setting the flag indicates to the manager that you don't want the widget to be managed. You can look at ttk, an extension to tkinter commonly included (in Python3 it's tkinter.ttk) if you don't want to completely remove the border, but just pick a different style.
Setting the TopMost Attribute
The method
root.wm_attributes("-topmost", 1)
Will put it at the top of the screen Combined, these will give you the desired behavior. You can then use other tkinter frames to decorate the widget as you please, i.e., add custom borders or close/minus buttons that would normally be included in the manager.
Resources
See this, e.g. for applying the topmost attribute
Make a tkinter window appear over all other windows
From Effbot about "overridedirect" (http://effbot.org/tkinterbook/wm.htm):
Sets or gets the override redirect flag. If non-zero, this prevents
the window manager from decorating the window. In other words, the
window will not have a title or a border, and it cannot be moved or
closed via ordinary means.
Note:
These functions can only be applied to the root window (Tk instance) or another Toplevel instance.

Categories

Resources