Search code examples
perlperltk

How do I clear the text within an entry or text widget when I mouse click on that entry/text in Perl/Tk


Can someone shed some lights on with my problem as title? I have both text and entry widgets within the form I created, but somehow I wish if I could do something such as for some of the text and entry widgets, I'll place the "" wording in it and if the user want to use that entry, they can just simply mouse click on the column and the "" wordings will automatically clear. May I know how to do that? Here is the code that I have without the mouse click to clear feature. Thanks.

#This section apply text  widget.
$mwf->Label(-text => 'Waiver',
    -justify => 'left'
    )->grid(-sticky => 'w', -column => 0, -row => 8);


my $scrollbar = $mwf->Scrollbar() 
->grid( -sticky => 'ns',-column=>2, -row => 8);

my $waiver = $mwf->Text(-height => 5,
        -width => 100,
        -background => "white",
        -wrap => 'word',
        -yscrollcommand => ['set' => $scrollbar], 
        )->grid(-sticky => 'w', -column => 1, -row => 8);

#This section apply entry widget.
$mwf->Label(-text => 'Exclude View',
-justify => 'left'
)->grid(-sticky => 'w', -column => 0, -row => 10);

my $exclude = $mwf->Entry(-width => 100,
        -background => "white",
        )->grid(-sticky => 'w', -column => 1, -row => 10);
        push @entries, $exclude ;
$exclude -> insert('end', '<optional>') ;

Solution

  • You can use a binding that is called when an event is triggered

    format $widget->bind('<event>' => callback);

    See the sample program below

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use Tk;
    use Tk::Entry;
    use Tk::TextUndo;
    
    my $win = new MainWindow;
    $win->geometry("400x300");
    
    my $entry = $win->Entry()->pack;
    my $text = $win->TextUndo()->pack;
    $text->insert('end', 'default');
    $entry->insert('end', 'default');
    
    $text->bind('<FocusIn>' => \&textfocus);
    $entry->bind('<FocusIn>' => \&entryfocus);
    MainLoop;
    
    sub textfocus {
    
        my $info = $text->Contents();
        if($info =~ /^default$/){
            $text->delete('1.0', 'end');
        }
    }
    
    sub entryfocus {
        my $info = $entry->get();
        if($info =~ /^default$/){
            $entry->delete('0.0', 'end');
        }
    }
    

    More info on perl\tk events here: http://docstore.mik.ua/orelly/perl3/tk/ch15_02.htm#INDEX-2191

    Edit:

    When the event is triggered, and reference to the calling widget is passed to the callback. Below is a way to use only one callback sub for each widget.

    $text->bind('<FocusIn>' => \&w_focus);
    $entry->bind('<FocusIn>' => \&w_focus);
    MainLoop;
    
    sub w_focus {
        my $widget = shift;
        my ($start, $info);
        if($widget == $text){
            $start = '1.0';
            $info = $widget->Contents();
        }
        else {
            $start = '0.0';
            $info = $widget->get();
        }
        if($info =~ /^default$/){
            $widget->delete($start, 'end');
        }
    }