Reputation: 49
I'm writing a GUI application with tkinter and I have different classes that represent different pages of my application. I'm trying to call a variable from one class to another, so I used the repr() function to gain some insight into how to call that object from one class to antother.
I called print(repr(listbox))
my listbox is within a class named SelectionPage
and is defined as listbox = tk.Listbox(self)
the representation printed as <tkinter.Listbox object .!selectionpage.!listbox>
I'm new to python and I'm confused as to what these exclamation marks mean. Is this even a good way to debugg?? Sorry if this is a duplicate question, I'm really confused and I couldn't find the answer elsewhere
Upvotes: 4
Views: 738
Reputation: 386265
What do exclamation marks mean in the representation of an object
They don't mean anything. Tkinter developers simply chose to give all of their autogenerated internal widget names a leading exclamation point.
Tkinter is just a python wrapper around a tcl/tk interpreter. In tcl/tk, a widget is represented as a hierarchy of widgets. For example, the root widget is .
. A frame in the root might be named .frame
. A listbox in that frame might be named .frame.lb
. Tcl is very broad in what it will accept - essentially, a widget name can be any character other than "." so using an exclamation point is legal, though uncommon in the tcl/tk world.
When you create a Tkinter widget by instantiating one of its classes, tkinter must create a valid widget name to pass to the tcl interpreter in order to create the actual widget. In older versions of Tkinter it used unique numbers (eg: '.4368693152.4368765368'
). In python3, tkinter chose to use more human-friendly names prefixed with an exclamation point.
As far as I know, the exclamation point has no special meaning, though I suppose it might be useful in determining whether a widget name was created by tkinter or through some other means.
I'm trying to call a variable from one class to another, so I used the repr() function to gain some insight into how to call that object from one class to antother.
There are almost certainly better ways to do that than to use the internal name of the widget. However, if you know the internal name of the widget (eg: ".!selectionpage.!listbox"
) and insist on doing it this way, you can convert the string name to the tkinter widget instance with the universal widget method nametowidget
.
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root)
listbox = tk.Listbox(frame)
listbox_name = str(listbox)
lb = root.nametowidget(listbox_name)
assert lb is listbox
By the way, you can give widgets a name if you don't like the autogenerated name. This works for all widgets except the root widget.
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, name="my_frame")
listbox = tk.Listbox(frame, name="my_listbox")
assert str(listbox) == ".my_frame.my_listbox"
Upvotes: 1