0

I wrote a collapsible frame widget and was hoping to give it a dock/undock property. From what I've read, widgets can't be placed "over" other widgets (except on canvases, which I wish to avoid) so I can't just "lift" the frame, and their master cannot be changed so I can't simply place the frame into a new Toplevel. The only other option I can think of is to copy the widget into the new Toplevel. Unfortunately, I don't see any options on the copy or deepcopy operations to change the Master before the new widget is created.

So, the question: Are these assumptions accurate, or is there a way to do any of these things?

If not, do I have any other options than the solution I put together here:

def copywidget(self, frame1, frame2):
    for child in frame1.winfo_children():
        newwidget = getattr(tkinter,child.winfo_class())(frame2)
        for key in child.keys(): newwidget[key] = child.cget(key)
        if child.winfo_manager() == 'pack':
            newwidget.pack()
            for key in child.pack_info():
                newwidget.pack_info()[key] = child.pack_info()[key]
        elif child.winfo_manager() == 'grid':
            newwidget.grid()
            for key in child.grid_info():
                newwidget.grid_info()[key] = child.grid_info()[key]
        elif child.winfo_manager() == 'place':
            newwidget.place()
            for key in child.place_info():
                newwidget.place_info()[key] = child.place_info()[key]
Reid Ballard
  • 1,480
  • 14
  • 19

2 Answers2

0

There is no way to reparent a widget to a different toplevel. The easiest thing is to make a method that recreates the widgets in a new parent.

Widgets can be stacked on top of each other, though it requires care. You can, for instance, use grid to place two widgets in the same cell, and you can use place to put one widget on top of another .

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
0

Using this answer you are able to copy one widget onto another master. Then, you simply forget the previous widget, and it will work as a moved widget.

Example code:

root = tk.Tk()

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

frame_to_clone = tk.Frame(frame1)
frame_to_clone.place(x=10, y= 15)
tk.Label(frame_to_clone, text='test text').grid(row=0, column=0)

frame2 = tk.Frame(root, bg='green', width=80, height=180)
frame2.grid(row=1, column=0, pady=(0, 5))

# Move frame_to_clone from frame1 to frame2
cloned_frame = clone_widget(frame_to_clone, frame2)
cloned_frame.place(x=10, y=15)

# frame_to_clone.destroy()  # Optional destroy or forget of the original widget

root.mainloop()

Gives:

Example of cloned frame on a new master

ALai
  • 739
  • 9
  • 18