How can you make an animated loading sign in Perl?

99封情书 提交于 2020-06-16 08:42:33

问题


I need to know how to make an animated loading sign in Perl for keeping people entertained while my program's checking for updates.

I've already tried using

print ".";
sleep(0.1);
print ".";

but that doesn't seem to work. Somebody please help me!

print ".";
sleep(0.1);
print ".";

isn't working

I just want the program to wait 1/10th of a second to print the next .


回答1:


Using Time::HiRes for sub-second timing needs, a few ways

use warnings;
use strict;
use feature 'say';    
use Time::HiRes qw(sleep);

STDOUT->autoflush(1);  # or $| = 1;
my $tot_sleep = 0; 

# Print dots
print "Loading "; 
while (1) {
    $tot_sleep += sleep 0.1;  print ".";
    last if $tot_sleep >= 2;
} 
say " done\n";  $tot_sleep = 0;

# Print "spinning" cursor while waiting
print "Loading ... ";
WAIT: while (1) { 
    for (qw(- \ | /)) {
        print;  $tot_sleep += sleep (0.1);  print "\b";
        last WAIT if $tot_sleep >= 2;
    }   
}
say "\b done\n";

# Print (overwrite) percentile completed (if you know the job size)
my $tot_percent = 0;  
while ($tot_percent < 100) { 
    $tot_percent += 5;  
    print "Loading ... $tot_percent%\r"; 
    sleep 0.1;
} 
say "\n";

I simulate "completion" (of loading) by adding up waits to 2 seconds. The if checks of this time thus stand for checks of whether "loading" completed, what presumably can be done at that point in the code (if it is a separate thread/process, or if this code runs in a forked process).


For a perhaps nicer "spinner" can use

use Time::HiRes qw(sleep);
use utf8;
use open qw(:std :encoding(UTF-8));
STDOUT->autoflush(1);

print "Waiting ... ";
WAIT: {
    my $tot_sleep;
    while (1) {
        for ('◑', '◒', '◐', '◓') {
            print; $tot_sleep += sleep 0.1; print "\b";
            last WAIT if $tot_sleep >= 5;
        }   
    }
};
say "\b done";

Idea for symbols borrowed from Term::Spinner::Color.

Such "spinners" of course don't give the visual clues of how long they wait(ed), like dots do.




回答2:


The existing solutions assume you actually want to sleep/wait. They're not easily adapted to replacing the sleep/wait with actual work. My solution is for when you're you're doing actual work (e.g. loading), not just waiting for something.

use Time::HiRes qw( );

$| = 1;

{
   my @syms = qw( - \ | / );
   my ( $i, $t );

   sub start_spinner {
      $t = Time::HiRes::time;
      $i = 0;
      print $syms[$i];
   }

   sub update_spinner {
      my $now = Time::HiRes::time;
      return if $now - $time < 0.1;  # Prevent spinner from spinning too fast.

      $time = $now;
      $i = ( $i + 1 ) % @syms;
      print "\b$syms[$i]";
   }

   sub stop_spinner {
      print "\b \b";
   }
}

start_spinner();
for (1..500) {
   update_spinner();          # Call this as often as possible.
   Time::HiRes::sleep(0.01);  # Simulate a little bit of work.
}
stop_spinner();

The key is using Time::HiRes's higher-resolution time (and sleep, if necessary), as well a rate limiter (return if $now - $time < 0.1;).

If you really do want to print a line of dots, the same approach can be used.

{
   my $t;

   sub start_spinner {
      $t = Time::HiRes::time;
   }

   sub update_spinner {
      my $now = Time::HiRes::time;
      return if $now - $time < 0.1;  # Prevent spinner from spinning too fast.

      $time = $now;
      print ".";
   }

   sub stop_spinner {
      print "\n";
   }
}



回答3:


The standard sleep function operates in integer seconds. You can use the sleep functions from Time::HiRes as a drop-in replacement that supports fractional seconds.

use strict;
use warnings;
use Time::HiRes 'sleep';

sleep 0.1;



回答4:


Yet another way, without using a module is by abusing select():

use warnings;
use strict;
$|=1;

while (1){
    print '.';
    select(undef, undef, undef, 0.1);
}

Or, a FreeBSD-style spinner for fun (uses a Linux system call to refresh screen. On Windows, change clear to cls):

while (1){
    for (qw(- \ | / -)){
        system 'clear';
        print $_;
        select(undef, undef, undef, 0.1);
    }
}


来源:https://stackoverflow.com/questions/57011212/how-can-you-make-an-animated-loading-sign-in-perl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!