This is a bit confusing, because your code example does not
seem to have much in common with your initial request, which
was:
I'm trying to write a Tk UI where text widgets autoexpand
to have the necessary height to show all text.
This would involve using the length of the string being
displayed in order to do one of two things: assign initial
"-width" and "-height" attributes when the text widget is
created, or else use the widget's "configure()" method
after it has been created. The former works if the string
length is known before creating the widget; the latter if
the string is created or changed after the widget is in place.
But you don't seem to be using the length of the string to
set the widget dimensions yet.
I haven't been able to find any way of determining how many
lines high the text widget needs to be to accomodate the
contained text in full view.
The easiest way (which can tend to make the text hard
to read at runtime) is to set the text widget for character
wrapping (as opposed to no-wrap or word-wrap), keep a fixed
width for the widget (say, 40), and divide the string length
by that width to decide how many lines are needed.
I've added a little to your example to demonstrate using
string length to configure widget dimensions. But I have
to admit there are things I don't get, like why you have
a set of smaller unscrolled text widgets in a bigger scrolled
one, or how the "print_info" is expected to help things.
use strict;
use Tk;
my $mw= MainWindow->new;
$mw->title('vartext');
my $f = $mw->Frame->pack(-side=>'bottom');
$f->Button(-text=>'Print',-command=>\&print_info)->pack(-side=>'left')
+;
my $t=$mw->Scrolled("Text", -width=>40, -wrap=>'none')->pack(-expand=>
+1, -fill=>'both');
my @widget_list = ();
my @strings = (" a..5 a.10 a.15 a.20 a.25 a.30 a.35 a.40 a.45 a.50",
" b..5 b.10 b.15 b.20 b.25 b.30 b.35 b.40",
" c..5 c.10 c.15 c.20 c.25 c.30",
" d..5 d.10 d.15 d.20",
);
my $wdth = 20;
foreach ( @strings ) {
my $hght = int( length() / $wdth );
$hght++ if ( length() % $wdth );
my $w= $t->Text( -width=>20, -height=>$hght, -wrap=>'char');
$w->insert('end',$_);
$t->windowCreate('end',-window=>$w);
$t->insert('end', "\n");
push @widget_list, $w;
}
sub print_info {
foreach my $text (@widget_list) {
print join " ", $text->yview;
print "\n";
my $index = $text->index('end');
print qq§ index : $index \n§;
}
print "----------\n";
}
MainLoop;
It would be a little trickier (but easier for a user to read) if you
used word wrapping instead of character wrapping: you
may have to replicate the widget's wrapping behavior to
figure out how many display lines will be needed -- or just
"pre-wrap" the lines yourself (and you
can find a lot of useful ideas for word-boundary-based line
wrapping by searching this site).
|