On 3/9/23 04:06, Alan Gauld wrote:
Thank you for the feedback, I appreciate the comments.
To add a little extra, there is actually a reason I lean toward overuse
of .config() for a lot of things even though they could be sent to the
constructor (other than that w["attribute"]= doesn't work in a lambda).
It comes from a use case I needed to solve in the shortcoming of tk with
frames not being scrollable, requiring a canvas.
When dynamically generating a series of widgets (i.e. loading a custom
json/xml layout config file), getting the scrollable area right is a bit
of a chore with a catch-22 situation.
With an inner frame in a canvas, pack_propogate(tk.True) is the default
on the frame, so that the children dictate the size, but in doing so it
prevents the frame from expanding to the full width of the area it's
given within the UI layout.
If you turn pack_propogate to tk.False, it breaks the ability for the
canvas to return bbox(tk.ALL) (which is kind of rough anyway as the tcl
docs state "The return value may overestimate the actual bounding box by
a few pixels."). So you end up with 1,1 and no way of knowing what size
scrollable area to set. Trying to obtain this value from a source
outside of the canvas requires knowing what you are placing the canvas
in each time, and was creating a similar catch-22 as the outer widget
doesn't know what it wants it's size to be without knowing what the
inner widget wants.. Switching to False, grabbing bbox, then back to
True of course causes an unsightly flicker and disrupts the smoothness
of the user experience.
So my solution is to create a widget instantiator which does a few
things, mainly adding something I call a "ghost".
it's something like this:
instantiator(qlass, master, config_args=None, pack_args=None,
init_args=None, ghost=False):
if not init_args:
init_args = {}
object = qlass(master=master, **init_args)
if hasattr(master, "ghost"):
object.ghost = qlass(master=master.ghost, **init_args)
elif ghost:
object.ghost = qlass(master=tk.Frame(), **init_args)
When i pass it a canvas and say ghost=True, the canvas gets a .ghost
duplicate, which is attached to an arbitrary frame that I never pack and
stays invisible.
Subsequent widgets created to the canvas then see that their parent,
starting with the canvas, have a ghost, and in return get a ghost of
themselves attached to their parents ghost.
This allows you to get an accurate bbox size from the unseen ghost
canvas that mirrors the visible version.
Keeping the init_args down to only what is necessary helps in
consistency, and the subsequent config_args and pack_args I have in
their respective dicts.
This also allows me to create a quality of life pack function I call ppack()
def ppack(self):
self.pack(**self.pack_args)
if hasattr(self, "ghost"):
self.ghost.pack(**self.ghost.pack_args)
return self
That allows each primary widget to manage and track their own set of
configurations.
Of course I could strip a lot of that crap out if I find a better and
smooth way of obtaining those bbox numbers, but I didn't see any quick
solutions in glancing through the tcl/tk source so I went with what
works for now.
--
https://mail.python.org/mailman/listinfo/python-list