in reply to Re: Tk::Widget's Busy method can result in LIFO event execution order?
in thread Tk::Widget's Busy method can result in LIFO event execution order?

while working on some example code and trying various things I found that I had been doing something wrong.

I was working with a TableMatrix widget created with the $mw->Scrolled() method. And I was trying to call Busy on the object returned by Scrolled. But Scrolled('TableMatrix') doesn't actually return a TableMatrix, it returns a Frame that happens to contain a TableMatrix. Duh! You can imagine how stupid I felt when I realized this.

So I was making the Frame Busy, and this does indeed ignore any future or already pending events generated by the Frame object or anything outside of it. But it doesn't ignore events generated by objects that are contained inside the Frame object. Not only does it not ignore them, but the current process must wait for these events from the child object to finish before it can proceed. Hence the LIFO behavior I was experiencing.

Here's some example code that exhibits what I was talking about. Pressing the t key prints a global count. The count is incremented with t event, so FIFO execution will result in a numerically increasing output sequence. But if you press t rapidly enough then you should see a numerically decreasing sequence, evidence of LIFO execution order from the point of the Busy statement.

note: you might want to adjust the loop count depending on the speed of your system to get the ideal delay

#!/usr/bin/perl -w use warnings; use strict; use Tk; use Tk::TableMatrix; my $mw = MainWindow->new; my $data = {}; my $t = $mw->Scrolled('TableMatrix', -variable => $data)->pack; $t->focus; $mw->bind('Tk::TableMatrix', '<t>', \&test_busy); #global counter our $i; sub test_busy { #give time to generate multiple events via keyboard # before Busy statement is reached. for my $k (0..2000000) { #whatever my $l = $k; } #store current value of counter #right before entering Busy statement my $j = ++$i; $t->Busy(); print "$j\n"; $t->Unbusy; } MainLoop;

What I should be doing is either calling Busy with the recurse option set to 1, or better yet using a reference to the actual TableMatrix widget to call Busy. Or proabably even better yet, both.

#!/usr/bin/perl -w use warnings; use strict; use Tk; use Tk::TableMatrix; my $mw = MainWindow->new; my $data = {}; my $t = $mw->Scrolled('TableMatrix', -variable => $data)->pack; $t->focus; $mw->bind('Tk::TableMatrix', '<t>', \&test_busy); #global counter our $i; sub test_busy { my $w = shift; #give time to generate multiple events via keyboard # before Busy statement is reached. for my $k (0..2000000) { #whatever my $l = $k; } #store current value of counter #right before entering Busy statement my $j = ++$i; $w->Busy(-recurse => 1); print "$j\n"; $w->Unbusy; } MainLoop;

Though I still have one issue I think. If for example, I wanted the same subroutine that I have bound to keypress-t to be the -command value for a button or menu command that exists on the main window, how do I pass to it the object reference to the TableMatrix? Or, what would be the best way? I admit, I haven't spent much time on this last issue, it just occurred to me, so I might figure out the answer on my own with a little reading, but if anybody wants to go ahead and show me the way, I wouldn't mind.