Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^3: How to display Tk window without waiting for user input

by kcott (Archbishop)
on Jan 17, 2021 at 07:29 UTC ( [id://11127023]=note: print w/replies, xml ) Need Help??


in reply to Re^2: How to display Tk window without waiting for user input
in thread How to display Tk window without waiting for user input

"The issue is that within the call to check_for_status(); is a webpage scrape; ..."

That's new information; however, it's fairly immaterial with respect to the Tk code.

"... there is no way to have the webpage "push" the status changes to me; I have to determine that myself."

Both points are obvious and accepted.

"For that reason a while (1) loop seems necessary."

It may seem necessary to you but, not only is it not necessary, it's still the wrong solution.

Consider the following (fully functional) script which produces a notification similar in appearance to what I get from my email client when a new email arrives.

#!/usr/bin/env perl use strict; use warnings; use constant { TIMER_INTERVAL => 1_000, NOTIFY_PERIOD => 10_000, }; use Tk; my $mw = MainWindow::->new(); $mw->configure(-title => 'Status Notification Manager'); $mw->geometry('320x60+50+100'); #$mw->withdraw(); my $status = _get_status(); my $last_status = $status; my $status_msg; _set_status_msg($status, \$status_msg); my $timer_id = $mw->repeat(TIMER_INTERVAL, sub { $status = _get_status(); if ($status ne $last_status) { $last_status = $status; _set_status_msg($status, \$status_msg); my $notify_panel = $mw->Toplevel(); $notify_panel->geometry('200x50-0-0'); $notify_panel->overrideredirect(1); my $msg_F = $notify_panel->Frame( )->pack( -side => 'left', -fill => 'both', -expand => 1, ); $msg_F->Label( -text => $status_msg, -anchor => 'w', )->pack( -side => 'left', -padx => 5, ); my $x_F = $notify_panel->Frame( )->pack( -side => 'left', -fill => 'y', ); my $x_B = $x_F->Button( -text => 'X', -bg => '#ff0000', -bd => 1, -relief => 'flat', -anchor => 'ne', -command => sub { if (Exists($notify_panel)) { $notify_panel->destroy(); } }, )->pack(); $notify_panel->raise(); $notify_panel->bell(); $mw->after(NOTIFY_PERIOD, sub { if (Exists($notify_panel)) { $notify_panel->destroy(); } }); } return; }); $mw->Button( -text => 'Exit', -command => sub { $timer_id->cancel(); exit; }, )->pack(-pady => 5); my $status_bar_F = $mw->Frame( )->pack(-side => 'bottom', -fill => 'x'); $status_bar_F->Label( -textvariable => \$status_msg, -anchor => 'w', -relief => 'sunken', )->pack(-fill => 'x'); MainLoop; sub _get_status { join ':', map sprintf('%02d', $_), (localtime())[2,1]; } sub _set_status_msg { my ($status, $msg_ref) = @_; $$msg_ref = 'Status: ' . $status; return; }

I've commented out the $mw->withdraw();. You had it in your original (OP) code. It does work with my code; however, it makes shutting down the application problematic. Here's an example of running my code with it left in, and then shutting it down:

ken@titan ~/tmp $ ./pm_11126974_tk_status_change_2.pl & [1] 618 ken@titan ~/tmp $ kill -HUP 618 ken@titan ~/tmp $ [1]+ Hangup ./pm_11126974_tk_status_change_2.pl ken@titan ~/tmp $

If you didn't leave the PID in plain sight, as I did for this example, you have additional work determining what the PID is. Alternatively, you can run it without the '&' at the end; minimise the console you used — effectively tying it up for whatever amount of time you want to monitor status changes (hours?) — and then end the application as needed.

I suggest leaving withdraw() out and just minimise the GUI, which is clearly labelled "Status Notification Manager". You can use this to query the last status between notifications; and just click on the "Exit" button when you're done.

Notice that I've used three methods related to Tk::after: repeat() handles checking for status changes; the ID from repeat() is used to cancel() that checking when the "Exit" button is used; and, after() is used (within the repeat() callback) to get rid if the notification panel after a period of time. See that documentation for more on those methods and additional information.

You may want to change the NOTIFY_PERIOD constant. You should almost definitely change the TIMER_INTERVAL constant; every five or ten minutes (300_000 or 600_000) would probably be better for accessing a webpage. Note that the values are in milliseconds.

My &_get_status just returns a time (hh:mm) for demonstration purposes. This is where your webpage status retrieval code should go.

I find all of the system sounds (bells, beeps, and so on) really annoying, so I've turned all of them off on my computer. The bell() method is untested by me, beyond the fact that its presence causes no problems: it's non-essential; you choose whether to leave or remove it.

See also: Tk; Tk::Widget; Tk::Wm.

Tests were run using: Win10; Cygwin; Cygwin XWin Server; Perl 5.32.0.

— Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11127023]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (3)
As of 2024-03-29 06:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found