How to get a widget name with tkinter's nametowidget function within a Class

Question:

I’m writing a tkinter mini project within a class, and am currently trying to get the name of a button widget but I get a Traceback error every time the program I try to run the program. I was curious as to how to go about fixing the nametowidget line to get the proper name of the widget.

from tkinter import *
import tkinter.messagebox
root = Tk()
class WindowPane(Frame):
    def __init__(self,master):
        Frame.__init__(self,master)
        self.master = master
        self.WindowWidget()

    def WindowWidget(self):
        self.stringer = StringVar()
        self.button1 = Button(text = "Click me")
        self.button1.place(x=200,y=50)
        print(self.master.nametowidget(".button1"))
root.geometry("200x200")
playback = WindowPane(root)
root.mainloop()
Asked By: Pen_Fighter

||

Answers:

The “name” in nametowidget isn’t the name of the variable used to keep a reference to the widget (ie: in this example it’s not “button1”). This makes sense because you can have multiple variables all pointing to the same object – how would python know which name you want?

The name refers to the internal widget name used by the embedded tcl/tk interpreter. Normally this is computed based on the name of the parent, the widget class and an optional number. For example, the first frame you create by default will have the name .!frame, the next frame will have the name .!frame2, and so on. The first button inside the first frame will be named .!frame1.!button1, etc.

You can see the name of any widget by printing out its string representation. For example, in your code, you could do print(str(self.button1) which will show you that the name is actually .!button

You can’t use anything built into tkinter to convert a string like "button1" to the actual widget. However, a variable such as self.button1 is an attribute of the current object, so you can use python’s built-in getattr function to get the value of an attribute with a given name.

In your case you can use getattr(self, "button1") to get a reference to the actual widget object.

Answered By: Bryan Oakley

Bryan Oakleys explanation did not work for me. Using dir on a Frame of f revealed that after packing an Entry e object into the frame that it did not become an attribute of f. Rather, it was a value of a dictionary f.children where the key was the name of e, !entry.

Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter as tk
>>> f = tk.Frame()
>>> dir(f)
['_Misc__winfo_getint', '_Misc__winfo_parseitem', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_bind', '_configure', '_displayof', '_do', '_getboolean', '_getconfigure', '_getconfigure1', '_getdoubles', '_getints', '_grid_configure', '_gridconvvalue', '_last_child_ids', '_name', '_nametowidget', '_noarg_', '_options', '_register', '_report_exception', '_root', '_setup', '_subst_format', '_subst_format_str', '_substitute', '_tclCommands', '_w', '_windowingsystem', 'after', 'after_cancel', 'after_idle', 'anchor', 'bbox', 'bell', 'bind', 'bind_all', 'bind_class', 'bindtags', 'cget', 'children', 'clipboard_append', 'clipboard_clear', 'clipboard_get', 'columnconfigure', 'config', 'configure', 'deletecommand', 'destroy', 'event_add', 'event_delete', 'event_generate', 'event_info', 'focus', 'focus_displayof', 'focus_force', 'focus_get', 'focus_lastfor', 'focus_set', 'forget', 'getboolean', 'getdouble', 'getint', 'getvar', 'grab_current', 'grab_release', 'grab_set', 'grab_set_global', 'grab_status', 'grid', 'grid_anchor', 'grid_bbox', 'grid_columnconfigure', 'grid_configure', 'grid_forget', 'grid_info', 'grid_location', 'grid_propagate', 'grid_remove', 'grid_rowconfigure', 'grid_size', 'grid_slaves', 'image_names', 'image_types', 'info', 'keys', 'lift', 'location', 'lower', 'mainloop', 'master', 'nametowidget', 'option_add', 'option_clear', 'option_get', 'option_readfile', 'pack', 'pack_configure', 'pack_forget', 'pack_info', 'pack_propagate', 'pack_slaves', 'place', 'place_configure', 'place_forget', 'place_info', 'place_slaves', 'propagate', 'quit', 'register', 'rowconfigure', 'selection_clear', 'selection_get', 'selection_handle', 'selection_own', 'selection_own_get', 'send', 'setvar', 'size', 'slaves', 'tk', 'tk_bisque', 'tk_focusFollowsMouse', 'tk_focusNext', 'tk_focusPrev', 'tk_setPalette', 'tk_strictMotif', 'tkraise', 'unbind', 'unbind_all', 'unbind_class', 'update', 'update_idletasks', 'wait_variable', 'wait_visibility', 'wait_window', 'waitvar', 'widgetName', 'winfo_atom', 'winfo_atomname', 'winfo_cells', 'winfo_children', 'winfo_class', 'winfo_colormapfull', 'winfo_containing', 'winfo_depth', 'winfo_exists', 'winfo_fpixels', 'winfo_geometry', 'winfo_height', 'winfo_id', 'winfo_interps', 'winfo_ismapped', 'winfo_manager', 'winfo_name', 'winfo_parent', 'winfo_pathname', 'winfo_pixels', 'winfo_pointerx', 'winfo_pointerxy', 'winfo_pointery', 'winfo_reqheight', 'winfo_reqwidth', 'winfo_rgb', 'winfo_rootx', 'winfo_rooty', 'winfo_screen', 'winfo_screencells', 'winfo_screendepth', 'winfo_screenheight', 'winfo_screenmmheight', 'winfo_screenmmwidth', 'winfo_screenvisual', 'winfo_screenwidth', 'winfo_server', 'winfo_toplevel', 'winfo_viewable', 'winfo_visual', 'winfo_visualid', 'winfo_visualsavailable', 'winfo_vrootheight', 'winfo_vrootwidth', 'winfo_vrootx', 'winfo_vrooty', 'winfo_width', 'winfo_x', 'winfo_y']
>>> f.children
{}
>>> e = tk.Entry(f)
>>> f.children
{'!entry': <tkinter.Entry object .!frame.!entry>}
>>> getattr(f, 'entry')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Frame' object has no attribute 'entry'
>>> getattr(f, '!entry')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Frame' object has no attribute '!entry'
>>>```
Answered By: Dont worry about it
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.