Search code examples
perltk-toolkitperltk

PerlTk Label - Different colour text in same widget


I have written a GUI which interacts with our psql database. For a given date, the gui displays a person list with various identifiers and bits of information. I use Tk::Table to display the data

eg
my $f_mainframe = $mw -> Frame(-bg=>'white');
$f_mainframe -> pack(-side=>'top', -expand=>1, -fill=>'both');
my $itable = $f_mainframe -> Table(-rows => 13,
                   -columns=>30,
                   -fixedrows => 1,
                   -fixedcolumns => 1,
                   -relief => 'raised') -> pack();

$itable->put(1,$firstnamecol,"First Name\nMYO");

Is it possible to colour "First Name" in black and "MYO" in Red?


Solution

  • By using the ->put method on a Tk::Table with a string argument, a simple Tk::Label widget is created. Labels can only be configured to have a single foreground color. To achieve what you want you can use a Tk::ROText (a read-only text widget) instead. The following code displays a label widget and a text widget, but the latter with different colors:

    use strict;
    use Tk;
    use Tk::ROText;
    
    my $mw = tkinit;
    
    # The monocolored Label variant
    my $l = $mw->Label
        (
         -text => "First Name\nMYO",
         -font => "{sans serif} 12",
        )->pack;
    
    # The multicolored ROText variant
    my $txt = $mw->ROText
        (
         -borderwidth => 0, -highlightthickness => 0, # remove extra borders
         -takefocus => 0, # make widget unfocusable
         -font => "{sans serif} 12",
        )->pack;
    $txt->tagConfigure
        (
         'blue',
         -foreground => "blue",
         -justify => 'center', # to get same behavior as with Tk::Label
        );
    $txt->tagConfigure
        (
         'red',
         -foreground => "red",
         -justify => 'center', # to get same behavior as with Tk::Label
        );
    $txt->insert("end", "First Name\n", "blue", "MYO", "red");
    # a hack to make the ROText geometry the same as the Label geometry
    $txt->GeometryRequest($l->reqwidth, $l->reqheight);
    
    MainLoop;
    

    As you see, it's much more typing to get the text widget variant working. So it's probably useful to abstract this code into a subroutine or a widget class (maybe something for CPAN?). Note also that you have to deal with text widget's geometry yourself. The label extends automatically to accommodate the label contents. A text widget has by default a geometry of 80x24 characters, and does not shrink or extend automatically based on its contents. In the sample I used a hack using GeometryRequest to force the same geometry as the equivalent label widget. Maybe you're fine with hardcoding -width and -height instead. Another solution could be to use the bbox() method of Tk::Text/Tk::ROText to calculate the geometry.