Re: Setting the minimum size of an autosized Tk widget
by Discipulus (Canon) on Dec 09, 2021 at 11:41 UTC
|
Hello olgo,
If I have understood your question, you can set the width dinamically based on the lenght of entries
my $atleast = 10; # default width
my $c2 = $f->BrowseEntry(-label => "Misc2:", -width => $atleast );
$c2->pack;
foreach my $entry ( qw(0 Large LargeEnoughToNotFitInTopWidget) ){
$c2->insert("end", $entry);
$atleast = length $entry if length $entry > $atleast;
}
$c2->configure( -width => $atleast );
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] |
Re: Setting the minimum size of an autosized Tk widget
by kcott (Archbishop) on Dec 09, 2021 at 14:44 UTC
|
G'day olgo,
"I am using pack geometry manager since my surrounding widgets are of varying size and type (Progressbars, buttons etc)."
That sounds like you're making assumptions, and at least some of them are incorrect.
Please explain that statement in more detail.
"Thus, using another geo manager like grid is not possible in this case (I know that this is one solution to the problem)."
It can't be "not possible" and, simultaneously, a "solution to the problem": they're mutually exclusive.
Perhaps a typo or just badly worded.
You seem to be saying that you can't use pack() and grid() in the same Tk application.
If so, that's incorrect (see my code below); if not, please be a bit more specific about what you mean.
"My problem is that the top (LabEntry) subwidget, which presents the currently selected entry, gets too small when displaying really small values."
I ran your sample code and couldn't replicate that problem.
In "Tk::Entry - Switch:-width",
you'll see "average-size characters of the widget's font".
If the entry is the smallest, i.e. one character, then "l" would probably be less than the average, and "W" would likely be greater. I'd normally add a couple of characters to the widest expected string.
The reason that I can't reproduce this issue, could be as simple as us having different default fonts;
or our X servers rendering the same font slightly differently.
"I have realized that I can either set a dynamic width using -width => 0 (works perfectly except for small values being barely visible) or a fixed width (works perfectly except large values are cropped)."
See my last point re the small values.
For large values, they may looked cropped but they aren't.
Running your example code and selecting your long entry, I see "LargeEnoug" (which fits with -width => 10).
Dragging the mouse cursor to the right, reveals more characters to the right while an equivalent amount is hidden on the left;
e.g. "geEnoughTo".
You can get the same effect by placing the insertion cursor in the text, then using the left and right arrow keys.
"Is there any way of stating a minimum size to the top widget so that it does not autosize smaller than this value, or is there some other mechanism I could use here?"
The biggest problem that I saw with your sample code was the GUI dimensions wildly jumping from one extreme to the other.
This is not a good UX solution and I would recommend dropping the idea of autosizing.
If your list is static, or has all entries of the same width, you can just add a -width value yourself.
If your list is dynamic, use a solution along the lines that ++Discipulus presented.
Take a look at the code below. You didn't provide sufficient up-front information, so this is just an example with suggestions.
Here's a brief outine of some of its features:
-
A geometry that allows everything to be seen at the outset. Autosizing, or manual resizing, are not necessary.
-
A nested layout which keeps related widgets together but separate from nearby widgets.
For example, $layer1_F splits into $be_F and $w_right_F:
the former has widgets using pack(); the latter has widgets using grid().
-
The BrowseEntry widgets align with uniform sizes and all entry selections can be seen in full: improved UX.
#!/usr/bin/env perl
use strict;
use warnings;
use Tk;
use Tk::BrowseEntry;
my $mw = MainWindow::->new();
$mw->geometry('400x200');
my $layout_F = $mw->Frame(
)->pack(-expand => 1, -fill => 'both');
my $layer1_F = $layout_F->Frame()->pack();
my $layer2_F = $layout_F->Frame()->pack();
my $be_F = $layer1_F->Frame(
)->pack(-side => 'left', -anchor => 'n');
my $w_right_F = $layer1_F->Frame(
)->pack(-side => 'left', -anchor => 'n');
my $w_bottom_F = $layer2_F->Frame(
)->pack();
my $be1 = $be_F->BrowseEntry(-label => 'Misc1: ', -width => 35);
$be1->pack(-anchor => 'w');
$be1->insert("end", "0");
$be1->insert("end", "LargeButWillStillFitInTopWidgetAsItExpands");
my $be2 = $be_F->BrowseEntry(-label => 'Misc2: ', -width => 35);
$be2->pack(-anchor => 'w');
$be2->insert("end", "0");
$be2->insert("end", "Large");
$be2->insert("end", "LargeEnoughToNotFitInTopWidget");
$w_right_F->Label(-text => 'Label 1')->grid();
$w_right_F->Label(-text => 'Label 2')->grid();
$w_bottom_F->Button(
-text => 'Exit', -command => sub { exit },
)->pack();
MainLoop;
| [reply] [d/l] [select] |
|
|
Ken,
thank you for your effort and detailed answer.
However, it does not answer my key question, namely whether there is a possiblity for stating a minimum size of the top entry widget of a BrowseEntry (or any Tk widget really). Maybe my english is just too poor for this to be clear but given all the other answers, I expect the answer to be "no".
I've actually just realized that the same problem goes also for e.g. Buttons. Of course, as with the example of the BrowseEntry before, I can programmatically set it to be of static, wide enough, width if its label is really small, but I am looking for Tk framework attributes to do it for me.
My note about different geo managers simply intended to state that I do know that placing the BrowseEntry in a grid geo context would in fact stretch it out to fit its "column companions", but given how my GUI looks, I simply wouldn't use a grid based placing of these widgets.
Programmatically changing the width based on the actual sizes of the entries (as suggested by ++Discipulus) will suffice however, although I would have expected such a feature to reside in the Tk libraries themselves. I wouldn't mind adding it myself but the level of Perl code in the Tk modules is above my paygrade
For the sake of further argument:
Button width code example.
The example shows that the "1" button gets irritatingly small, whereas the "TooLargeToBeVisible" button label is not fully shown
(I would have liked an attribute -minWidth=>10 together with the -width=>0, making "1" and "2" width 10 and the others as wide as needed to show the entire label)
use Tk;
my $top = MainWindow->new;
my $f = $top->Frame;
$f->Button(-text => "1", -width => 0)->pack();
$f->Button(-text => "LargeButStillQuiteVisible", -width => 0)->pack();
$f->Button(-text => "2", -width => 10)->pack();
$f->Button(-text => "TooLargeToBeVisible", -width => 10)->pack();
$f->pack;
MainLoop;
| [reply] [d/l] |
Re: Setting the minimum size of an autosized Tk widget
by tybalt89 (Monsignor) on Dec 10, 2021 at 13:24 UTC
|
#!/usr/bin/perl
use strict; # https://perlmonks.org/?node_id=11139495
use warnings;
use Tk;
use Tk::BrowseEntry;
my $top = MainWindow->new;
my $f = $top->Frame;
my $c1 = $f->BrowseEntry(-label => "Misc1:", -width => 0);
$c1->pack(-fill => 'x', -expand => 1);
$c1->insert("end", "0");
$c1->insert("end", "LargeButWillStillFitInTopWidgetAsItExpands");
my $c2 = $f->BrowseEntry(-label => "Misc2:", -width => 0);
$c2->pack(-fill => 'x', -expand => 1);
$c2->insert("end", "0");
$c2->insert("end", "Large");
$c2->insert("end", "LargeEnoughToNotFitInTopWidget");
$f->Frame(-width =>160)->pack; # strut for min width...
$f->pack(-fill => 'x', -expand => 1);
MainLoop;
Or maybe I don't understand your problem at all.
| [reply] [d/l] |
|
|
Again, thanks for your effort!
However, the proposed solution works only as long as there is just one "column" of widgets, I think.
Now realizing that my minimum example was a bit too minimum... sorry about that. One thing I did not tell you about was that I am using the form geometry handler. I did not think it mattered but obviously it does.
Basically, I am placing a number of widgets in a form, one following the other in both x and y dimensions.
A better example of the code I am struggling with is thus the following (still minimized - single line of 2 BrowseEntrys here) code example (courtesy of tybalt89):
use strict;
use warnings;
use Tk;
use Tk::BrowseEntry;
my $top = MainWindow->new;
my $f = $top->Frame;
my $c1 = $f->BrowseEntry(-label => "Misc1:", -width => 0);
$c1->form(-fill => 'x');
$c1->insert("end", "0");
$c1->insert("end", "LargeButWillStillFitInTopWidgetAsItExpands");
my $c2 = $f->BrowseEntry(-label => "Misc2:", -width => 0);
$c2->form(-fill => 'x', -left => $c1);
$c2->insert("end", "0");
$c2->insert("end", "Large");
$c2->insert("end", "LargeEnoughToNotFitInTopWidget");
$f->Frame(-width =>160)->form(); # strut for min width...
$f->pack(-fill => 'x', -expand => 1);
MainLoop;
| [reply] [d/l] |
|
|
#!/usr/bin/perl
use strict; # https://perlmonks.org/?node_id=11139495
use warnings;
use Tk;
use Tk::BrowseEntry;
my $top = MainWindow->new;
my $f = $top->Frame;
my $f1 = $f->Frame->form(-fill => 'x');
$f1->Frame(-width => 150)->pack; # strut
my $c1 = $f1->BrowseEntry(-label => "Misc1:", -width => 0,
)->pack(-fill => 'x', -expand => 1);
$c1->insert("end", "0");
$c1->insert("end", "LargeButWillStillFitInTopWidgetAsItExpands");
my $f2 = $f->Frame->form(-fill => 'x', -left => $f1);
$f2->Frame(-width => 150)->pack; # strut
my $c2 = $f2->BrowseEntry(-label => "Misc2:", -width => 0,
)->pack(-fill => 'x', -expand => 1);
$c2->insert("end", "0");
$c2->insert("end", "Large");
$c2->insert("end", "LargeEnoughToNotFitInTopWidget");
$f->pack(-fill => 'x', -expand => 1);
MainLoop;
| [reply] [d/l] |
Re: Setting the minimum size of an autosized Tk widget
by Anonymous Monk on Dec 09, 2021 at 11:23 UTC
|
Where do you configure a labentry? Use Tk::WidgetDump to explore | [reply] |
|
|
I did not configure the LabEntry subwidget. It is a part of the BrowseEntry widget (consisting of Labentry, Arrow, slist etc). WidgetDump only shows what I find using the debugger(?).
| [reply] |