Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Perl/Tk stdin NOT text box, only one part of code

by cniggeler (Sexton)
on Jul 01, 2020 at 15:50 UTC ( [id://11118763] : perlquestion . print w/replies, xml ) Need Help??

cniggeler has asked for the wisdom of the Perl Monks concerning the following question:

Hi, in a large-size perl/Tk program we are adding tags. Sometimes there are tens of thousands of tags to add, and this can take a lot of user real-time. Our window has a status bar, so I'd like to have something in it like,

Adding 1500 of 37885 tags. Press 's' to stop adding tags...

and have that update every 500 tags. My question is, how can I detect the user entered 's' at this point in the code? I thought of adding a key binding, which I guess is the only way to do so, but would this intercept the user, say, typing a filename containing a 's' in a dialog box? In that case, is there a way to enable the key binding at just the point I need it, then disable it at the end? Or do I have to use something more unlikely, like CTRL+S?

Or is there a better way? Online searches have not been fruitful. Thank you!

Replies are listed 'Best First'.
Re: Perl/Tk stdin NOT text box, only one part of code
by choroba (Cardinal) on Jul 01, 2020 at 20:29 UTC
    When you're typing into the text box, it has focus. Cancel the binding to stop adding tags when the text box gets focus, enable it back when the focus goes somewhere else.
    #!/usr/bin/perl use warnings; use strict; use Tk; use Tk::ROText; my $mw = 'MainWindow'->new(-title => 'Tagging'); $mw->Label(-text => 'Here, the tags are being created:')->pack; my $rotext = $mw->ROText->pack; $mw->Label(-text => 'Try typing here, including the letter "s":')->pac +k; my $text = $mw->Text(-width => 20, -height => 3)->pack; $mw->Entry(-text => 'Click here to change focus.', -state => 'readonly +')->pack; my $label = $mw->Label(-textvariable => \ my $l)->pack; my $max = 1000; my ($i, $repeat, $stop); $repeat = $mw->repeat(10, sub { return if $stop; ++$i; $rotext->insert('end', $i, "T$i"); $l = "$i/$max tags added. Press 's' to stop."; $repeat->cancel if $i == $max; }); sub stop { $stop = ! $stop; $l =~ s/stop/start/; } $mw->bind('<s>', \&stop); $text->bind('<FocusIn>', sub { $mw->bind('<s>', "") }); $text->bind('<FocusOut>', sub { $mw->bind('<s>', \&stop) }); MainLoop();

    Update: Fixed the problem with "stop" not being updated.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      Thank you! Since there are multiple spots for user input (the one I mentioned was just an example), I created a dialog box warning them of a possibly time-consuming operation and letting them skip the step by choosing "Cancel".
Re: Perl/Tk stdin NOT text box, only one part of code
by Anonymous Monk on Jul 02, 2020 at 12:07 UTC
    37885 tags? Thats for humans to click at?
      Yeah, that's why I'm trying to do this! It's their data; my goal is to relay to the user it's a lot and maybe choose to filter their data first.