Skip to content Skip to sidebar Skip to footer

Is There A Way To Clone A Tkinter Widget?

I'm trying to create of grid of widgets. This grid of widgets starts out as labels telling me their coordinates. I then have a list of starting and ending points for buttons that w

Solution 1:

There is no direct way to clone a widget, but tkinter gives you a way to determine the parent of a widget, the class of a widget, and all of the configuration values of a widget. This information is enough to create a duplicate.

It would look something like this:

def clone(widget):
    parent = widget.nametowidget(widget.winfo_parent())
    cls = widget.__class__

    clone = cls(parent)
    for key in widget.configure():
        clone.configure({key: widget.cget(key)})
    return clone

Solution 2:

To expand the answer by Bryan Oakley, here a function that allows you to completely clone a widget, including all of its children:

defclone_widget(widget, master=None):
    """
    Create a cloned version o a widget

    Parameters
    ----------
    widget : tkinter widget
        tkinter widget that shall be cloned.
    master : tkinter widget, optional
        Master widget onto which cloned widget shall be placed. If None, same master of input widget will be used. The
        default is None.

    Returns
    -------
    cloned : tkinter widget
        Clone of input widget onto master widget.

    """# Get main info
    parent = master if master else widget.master
    cls = widget.__class__

    # Clone the widget configuration
    cfg = {key: widget.cget(key) for key in widget.configure()}
    cloned = cls(parent, **cfg)

    # Clone the widget's childrenfor child in widget.winfo_children():
        child_cloned = clone_widget(child, master=cloned)
        if child.grid_info():
            grid_info = {k: v for k, v in child.grid_info().items() if k notin {'in'}}
            child_cloned.grid(**grid_info)
        elif child.place_info():
            place_info = {k: v for k, v in child.place_info().items() if k notin {'in'}}
            child_cloned.place(**place_info)
        else:
            pack_info = {k: v for k, v in child.pack_info().items() if k notin {'in'}}
            child_cloned.pack(**pack_info)

    return cloned

Example:

root = tk.Tk()

frame = tk.Frame(root, bg='blue', width=200, height=100)
frame.grid(row=0, column=0, pady=(0, 5))

lbl = tk.Label(frame, text='test text', bg='green')
lbl.place(x=10, y=15)

cloned_frame = clone_widget(frame)
cloned_frame.grid(row=1, column=0, pady=(5, 0))

root.mainloop()

Gives:

Example of cloned frame

Post a Comment for "Is There A Way To Clone A Tkinter Widget?"