Win32::GUI and Scrolling Text

J

jackbarnett

Anyone have an example of a perl script that use Win32::GUI for
scrolling text ?

An example would be something like
this:http://tailforwin32.sourceforge.net/ - but um, written in perl

It automatically updates the screen buffer with newest lines on bottom
without overwriting old info. How do you do that in Perl using
Win32::GUI ?
 
J

jackbarnett

A. Sinan Unur said:
I don't know.


Put together GUI with a textbox, update the textbox using File::Tail.

You might also want to consult the Perl-Tk FAQ, question 18.1.

Sinan

PS: You might want to use Perl-Tk for the GUI so that your program run on
other platforms too.

--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html


thanks. Yea I have the part that tails the file working (works in
console window) and updates on new line... I have a GUI with a text
box... but I can't get the text box to scroll... (I don't know how to
update the box).

any ideas?
 
Z

zentara

thanks. Yea I have the part that tails the file working (works in
console window) and updates on new line... I have a GUI with a text
box... but I can't get the text box to scroll... (I don't know how to
update the box).

any ideas?

Usually you need to tell the text widget to "see" or "yview" the 'end'.
You may also need to update the widget manually , it depends,
and I don't use win32 so I can't say for sure.

If you absolutely insist on using the win32gui modules, you might ask
this on http://perlmonks.org. There are a few monks there familiar with
win32gui.

If you are willing to switch to Tk, here is a simple set of scripts to
test. (Tested on linux)

######## the actual file tail display of z.txt #####################
#!/usr/bin/perl
use strict;
use Tk;
use IO::Handle;

my $H=IO::Handle->new;
open($H,"tail -f -n 50 z.txt |") or die $!;

my $main = MainWindow->new;

my $t = $main-> Scrolled('Text',
-wrap=>'none')->pack(-expand=>1);

$main->fileevent(\*$H,'readable',[\&fill,$t]);

MainLoop;

sub fill {
my ($w) = @_;
my $text;
my $text =<$H>;
$w->insert('end',$text);
$w->yview('end');
#$w->see('end'); #same thing
#$w->update; #may be needed

}
__END__
#################################################


####### A script to pump z.txt for testing ################

#!/usr/bin/perl
use warnings;
use strict;

$| = 1;

open (ZH, "> z.txt") or die "$_\n";

# autoflush ZH
my $ofh = select(ZH);
$| = 1;
select($ofh);

while(1){
print ZH time."\n";
print '#'; #action indicator
select(undef,undef,undef,.1);
}
__END__
 
H

hbm

Anyone have an example of a perl script that use Win32::GUI for
scrolling text ?

What I think you're saying can be done with a textfield and its Append
method (inside a DoEvents loop). Add:

-vscroll => 1,
-multiline =>1,

to your textfield constructor. Then use a DoEvents loop like:

while(Win32::GUI::DoEvents() != -1) {
if ( [...whatever happens] ) {
$Window->Textfield1->Append($wedwd)
}


Haven't thought this through but that might be a start, hope it helps
Henry
 
J

jackbarnett

TK stuff is working.... this is what I'm trying to do (can't use tail
and that ulgy filehandler thing you got there):

Here is my code. basically I need the "dostuff" to run the entire
time, but looks like it's also fighting with MainLoop() [keeps locking
up application, not updating, etc]

Thoughts?


#!/usr/bin/perl

use Tk;
use IO::Handle;
use Sys::Hostname;
use strict;


my $main = MainWindow->new;
my $t = $main-> Scrolled('Text',
-wrap=>'none')->pack(-expand=>1);

my $file = "z.txt";
my $sleeptime=1;

my $hello = $main->Button(
-text => 'Hello, world',
-command => sub { &dostuff; } );
$hello->pack;

# unless (fork) { &dostuff(); }
MainLoop();
exit();

sub dostuff() {
open (FILE, "$file")
or die ("Can't open file: $file: $!\n");

for (;;) {
while ( <FILE> ) {
my $line=$_;

chomp($line);
print ("$line\n");

$t->insert('end',"$line\n");
$t->yview('end');
$t->see('end'); #same thing
$t->update();
}
sleep ($sleeptime);
FILE->clearerr();
}
close (FILE)
or warn ("Can't close file: $file: $!\n");
}
 
Z

zentara

TK stuff is working.... this is what I'm trying to do (can't use tail
and that ulgy filehandler thing you got there):

Here is my code. basically I need the "dostuff" to run the entire
time, but looks like it's also fighting with MainLoop() [keeps locking
up application, not updating, etc]

Thoughts?

Yeah, gui apps run a thing called an "event loop" which must
be your first concern. Otherwise, you get a condition called
"blocking the gui", where the gui becomes unresponsive. You
should not use sleep() or while(1) loops unless you really are sure
what you are doing. Those will block the gui eventloop.

That "ugly filehandler" (as you refer to it) is what gui programs use
to watch filehandles, without blocking the gui. It is sort of like
IO::Select, but designed to work within an event-loop system.
It watches filehandles with blocking the gui.

The preferred method is to use fileevent, but since you say you
can't use it (possible problems on win32?), I've changed your
example to use a timer, instead of sleep. It is probably very
inefficient to do it this way, but here it is. It probably wouldn't
be too bad if your timer was set to 10 seconds ( 10000). And you
probably would want to clear your text box every 10th run (or whatever),
since you are rereading the whole file each time.

#!/usr/bin/perl
use warnings;
use strict;
use Tk;

my $main = MainWindow->new;
my $t = $main-> Scrolled('Text',
-wrap=>'none')->pack(-expand=>1);

my $file = "z.txt";
my $timer;

my $hello = $main->Button(
-text => 'Start It',
-command => sub { &start_it } );
$hello->pack;

MainLoop();

sub start_it{
$hello->configure(-state => 'disabled'); #prevent double starts
$timer = $main->repeat(1000,\&dostuff); # 1000 milliseconds
}

sub dostuff() {
open (FILE, "$file")
or die ("Can't open file: $file: $!\n");

while ( <FILE> ) {
my $line=$_;

chomp($line);
print ("$line\n");

$t->insert('end',"$line\n");
$t->yview('end');
$t->see('end'); #same thing
$t->update();
}

close (FILE)
or warn ("Can't close file: $file: $!\n");

}
__END__
 
Z

zentara

Opps , I made a small typo, and I didn't want it to confuse you.
That "ugly filehandler" (as you refer to it) is what gui programs use
to watch filehandles, without blocking the gui. It is sort of like
IO::Select, but designed to work within an event-loop system.
It watches filehandles with blocking the gui.
^^^^^^^^^^^^^

It watches filehandles withOUT blocking the gui.

( referring to Tk's fileevent method )
 
J

jackbarnett

I need an infite loop. Basically what I'm trying to do is a tail...
reading in entire file and when I get to the end of the file; sleep
for X Seconds and then see if there is any more lines on the end of the
file is unread, else sleep again and repeat.

I don't need to update the window with the entire file, only need to
update the window with the new lines (appeneded at the end of the
buffer).

for example, in a normal text console under Win32 I can do this:


for(;;) {
while ( <FILE> ) {
my $line=$_;
chomp($line);
print ("$line\n");
}
sleep (1);
FILE->clearerr();
}


That reads in entire file, when it gets to end, it sleeps for 1 second.
It then loops back and starts reading where it left off (if there are
any new lines it prints them) then repeats.

I don't need this "event handler loop" stuff getting in my way. I
tried forking it off (so it could run in a differant thread and update
whatever it needs) but that causes the GUI to hang.

I want to control directly what I'm doing or not doing with the file.
It's not the EventHandler's bussiness what I'm doing with this file in
the privacy of my own code.

Can I just do a fork and say "Here Mr. TK GUI, you run in a differant
thread and do whatever you need to do. I'll send you data if I want
you to update something, else stop getting all up in my code like
that".

Basically I want a nice GUI interface with fancy buttons and stuff and
then imbedded in the GUI a window that acts like a "stupid console".

Does that make sense?

Basically I want to do this:
http://tailforwin32.sourceforge.net/

But in Perl.

TK/Win32, I don't care. Just some type of nice GUI interface.
 
J

jackbarnett

btw, thanks for your replies. I appericate it.

I was also wondering, do you know of any online documentation for
Perl/TK? I think I should start there... some newbie guide, cause
don't think I'm getting the basic concepts here.
 
Z

zentara

btw, thanks for your replies. I appericate it.

I was also wondering, do you know of any online documentation for
Perl/TK? I think I should start there... some newbie guide, cause
don't think I'm getting the basic concepts here.

First there are the perldocs. Type "perldoc Tk" for an overview.
Then to get individual widgets, type "perldoc Tk::Text" or
"perldoc Tk::Canvas", for example.

If you are using Windows, ActiveState has the best docs. They
have many examples of windows-specific scripts, and I even check their
docs for linux usage.
http://aspn.activestate.com/ASPN/docs/ActivePerl/5.8/site/lib/Tk.html



There are alot of Tk mini-tutorials to be found on google, but the
best learning source is the book "Mastering Perl/Tk" by Steven Lidie.
Read that book, and you will be totally up to speed.

You can get an online version at O'Reilleys Safari website, where
you can probably browse some of it for free.
http://safari.oreilly.com/

The nice thing about the online version, is you can cut'n'paste code
to teat yourself.





Otherwise, there is an active newsgroup for Tk,
comp.lang.perl.tk
You can ask for code help there, but they usually expect to see
some effort on your part.

http://groups.google.com is a treasure box full of Tk code snippets.
Just groups.google for some keywords like " Tk fileevent" and you will
get hundreds of snippets to test and help you learn.


There is also http://perltk.org/ where there are some interesting
articles are varous difficult Tk topics.

Good luck.
 
Z

zentara

I need an infite loop. Basically what I'm trying to do is a tail...
reading in entire file and when I get to the end of the file; sleep
for X Seconds and then see if there is any more lines on the end of the
file is unread, else sleep again and repeat.

Yeah, that is why in my first example I used a piped-open to tail the
file, then read that filehandle with fileevent. That essentially forks
off the tail process. Now on windows, fork is emulated using threads,
so you could use the tail code in a thread, and read it thru shared
variables.

Since there are so many ways to do this, why don't you check out
http://perlmonks.org/?node=tail+win32&go_button=Search

and read the links where some win32 savvy perlmonks discuss it.
I'm a linux guy, and I'm probably missing some win32-expertise.

I don't need to update the window with the entire file, only need to
update the window with the new lines (appeneded at the end of the
buffer).

Yeah, the problem I see in my previous example is the repetitive
opening /closing the file. It would be best to open it just once.
But see below for a hack.
for example, in a normal text console under Win32 I can do this:


for(;;) {
while ( <FILE> ) {
my $line=$_;
chomp($line);
print ("$line\n");
}
sleep (1);
If you put this sleep in a thread, it would be Ok. But in a Tk app,
you should not use sleep, use a non-blocking delay
$mw->after(1000); # will simulate a 1 second delay without blocking
FILE->clearerr();
}


That reads in entire file, when it gets to end, it sleeps for 1 second.
It then loops back and starts reading where it left off (if there are
any new lines it prints them) then repeats.

I don't need this "event handler loop" stuff getting in my way. I

Sorry, but to do it correctly, you need fileevent, or IO::Select which
essentially does the same thing ( but you must account for blocking the
event-loop with IO::Select, like using after and update in the loop as
shown below).
tried forking it off (so it could run in a differant thread and update
whatever it needs) but that causes the GUI to hang.
I want to control directly what I'm doing or not doing with the file.
It's not the EventHandler's bussiness what I'm doing with this file in
the privacy of my own code.

You can try ( or use an IO::Select can_read loop )

for(;;) {
while ( <FILE> ) {
my $line=$_;
chomp($line);
print ("$line\n");
$textbox->insert('end', "$line\n");
}
$mw->after(1000); # will simulate a 1 second delay without blocking
$mw->update; # force the event loop to update
FILE->clearerr();
}

Can I just do a fork and say "Here Mr. TK GUI, you run in a differant
thread and do whatever you need to do. I'll send you data if I want
you to update something, else stop getting all up in my code like
that".

Basically I want a nice GUI interface with fancy buttons and stuff and
then imbedded in the GUI a window that acts like a "stupid console".

Does that make sense?

Basically I want to do this:
http://tailforwin32.sourceforge.net/

But in Perl.

TK/Win32, I don't care. Just some type of nice GUI interface.

Here is a discussion of how someone on perlmonks did a win32
tail. See the code in the reply by msemtd
http://perlmonks.org/?displaytype=print;node_id=297848;replies=1

#########################################################

I would probably use a thread myself. Here is a simple
thread example. It has a drawback, that it takes a few seconds
to re-pickup on the output if the pumper script stops and restarts.
####################################################
#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;

# must setup thread code before any Tk code is used
# to avoid Tk thread-safety problems

my @logdata : shared;
my $thread_die : shared;
@logdata = ();
$thread_die = 0;

my $thread = threads->new( \&work );
############################################

use Tk;

my $mw = MainWindow->new(-background => 'gray50');

my $tframe = $mw->Frame( -background => 'gray50',-borderwidth=>10 )
->pack(-side =>'top' ,-fill=>'y');
my $bframe = $mw->Frame( -background => 'gray50',-borderwidth=>10 )
->pack(-side =>'bottom',-fill =>'both' );


my $text = $tframe->Scrolled("Text",
-scrollbars => 'ose',
-background => 'black',
-foreground => 'lightskyblue',
)->pack(-side =>'top', -anchor =>'n');

my $exit_button = $mw->Button(-text => 'Exit',
-command => sub{
$thread_die = 1; #kill thread
exit;
})->pack();


my $timer = $mw->repeat(1000, sub{
lock( @logdata );
my @in = @logdata; #copy it
@logdata = (); #clear out old log lines
# cond_broadcast( @logdata );
$text->insert('end', "@in");
$text->see('end');
});


MainLoop;

##################################################################
sub work{

$|++;
open(FH,"< z.log") or die "$!\n";

while(1){
while(<FH>){
push @logdata, $_;
if( $thread_die == 1 ){return} #kill thread
}
}

}
#####################################################################
__END__


############ and the pumper script ############################

#!/usr/bin/perl
use warnings;
use strict;

$| = 1;

open (ZH, "> z.log") or die "$_\n";

# autoflush ZH
my $ofh = select(ZH);
$| = 1;
select($ofh);

while(1){
print ZH time."\n";
print '#'; #action indicator
select(undef,undef,undef, 1);
}
__END__
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top