Re-parenting widgets with Tk’s [pack]

Just a short post about re-parenting widgets in Tcl/Tk, using the [pack] geometry manager.
Short because the solution is simple (and documented), but I couldn’t find it easily since I did not correctly understand the problem I was having.

So, I wanted to move a widget .frame.widget packed in a frame .frame into a sub-frame .frame.subframe. Note that .frame.widget and .frame.subframe are created in this order (the problem doesn’t arise otherwise).
Doing the simple

pack .frame.widget -in .frame.subframe

somehow didn’t work: the widget indeed disappeared from its previous master .frame but did not show up in its new master .frame.subframe (though it was listed by [pack slaves .frame.subframe]).

The reason for this is stacking order: .frame.widget was correctly re-packed in .frame.subframe, but was obscured by it (since .frame.subframe is created after .frame.widget and thus highest in stacking order).

The solution for this is to [raise] the widget above its new master in the stacking order:

raise .frame.widget .frame.subframe

This is all explained in the “Packing Order” section of the [pack] documentation, and the [raise] documentation even provides a nice example that specifically addresses the exact same case I was in.


Bonus: the re-packing command can be made to preserve all attributes of the previous packing using [pack info] like so:

pack .frame.widget -in .frame.subframe {*}[lrange [pack info .frame.widget] 2 end]

Warning: a widget cannot be re-packed (or packed, for that matter) inside a widget that’s not either its parent, sibling or a descendant of one of its siblings.

Note: the term re-parenting used throughout this post is abusive: the widget isn’t strictly re-parented (its parent remains .frame as its name remains .frame.widget), it is rather re-mastered, but that sounded a bit weird and less understandable.

Leave a Reply

Your email address will not be published. Required fields are marked *