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

TableMatrix asynch update of cells

by olgo (Acolyte)
on Apr 25, 2022 at 11:35 UTC ( [id://11143267]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings.
I am struggling with TableMatrix cell updates and hope someone is able to assist me.
My application consists in defining a grid, associating its cell contents with a hash and then updating the hash in a timer event, hoping to see the updates in the TableMatrix.
The problem is that this does not work very well.

I have come to the conclusion that any on of the following methods "work", i.e. actually get the shown data in the cell to reflect what is in the associated variable hash:
1. activating the cell and then activating another cell.
2. calling colWidth on any column.
3. updating the top window.

However, all of these methods have bad side effects and seem less than optimal since they cause flicker or take too long to perform. (My timer runs with 5Hz).
Slightly modified example from TableMatrix follows:
The example _should_ show a cell with updating contents in cell 4,0 but without uncommenting my attempts of updating, it does not.
## basic ## ## This demo shows the basic use of the table widget ## ## jeff.hobbs@acm.org use Tk ':eventtypes'; use Tk::TableMatrix; use Data::Dumper qw( DumperX); my $top = MainWindow->new; my $arrayVar = {}; foreach my $row (-1..6){ foreach my $col (-2..5){ $arrayVar->{"$row,$col"} = "r$row, c$col"; } } ## Test out the use of a callback to define tags on rows and columns sub rowSub{ my $row = shift; return "OddRow" if( $row > 0 && $row % 2) } sub colSub{ my $col = shift; return "OddCol" if( $col > 0 && $col%2) ; } my $label = $top->Label(-text => "TableMatrix v1 Example"); my $t = $top->Scrolled('TableMatrix', -rows => 8, -cols => 8, -width => 6, -height => 6, -titlerows => 1, -titlecols => 2, -variable => $arrayVar, -roworigin => -1, -colorigin => -2, -rowtagcommand => \&rowSub, -coltagcommand => \&colSub, -colstretchmode => 'last', -rowstretchmode => 'last', -selectmode => 'extended', -sparsearray => 0, ); my $button = $top->Button( -text => "Exit", -command => sub{ $top->des +troy}); # hideous Color definitions here: $t->tagConfigure('OddRow', -bg => 'orange', -fg => 'purple'); $t->tagConfigure('OddCol', -bg => 'brown', -fg => 'pink'); $t->colWidth( -2 => 7, -1 => 7, 1=> 5, 2 => 8, 4=> 14); $label->pack( -expand => 1, -fill => 'both'); $t->pack(-expand => 1, -fill => 'both'); $button->pack(-expand => 1, -fill => 'both'); my $cnt; sub Timer { print "Now\n"; my $variable = $t->cget( -var); $variable->{"4,0"}="Test".$cnt++; $t->activate("4,0"); #$t->activate("4,0"); #$t->colWidth( -2 => 7, -1 => 7, 1=> 5, 2 => 8, 4=> 14); #$t->update(); $top->after(1000, \&Timer); return 1; } $top->after(1000, \&Timer); Tk::MainLoop;

Replies are listed 'Best First'.
Re: TableMatrix asynch update of cells
by tybalt89 (Monsignor) on Apr 25, 2022 at 17:24 UTC

    Try using $t->curvalue() seems to work for me.

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11143267 use warnings; use Tk ':eventtypes'; use Tk::TableMatrix; use Data::Dumper qw( DumperX); my $top = MainWindow->new; my $arrayVar = {}; foreach my $row (-1..6){ foreach my $col (-2..5){ $arrayVar->{"$row,$col"} = "r$row, c$col"; } } ## Test out the use of a callback to define tags on rows and columns sub rowSub{ my $row = shift; return "OddRow" if( $row > 0 && $row % 2) } sub colSub{ my $col = shift; return "OddCol" if( $col > 0 && $col%2) ; } my $label = $top->Label(-text => "TableMatrix v1 Example"); my $t = $top->Scrolled('TableMatrix', -rows => 8, -cols => 8, -width => 6, -height => 6, -titlerows => 1, -titlecols => 2, -variable => $arrayVar, -roworigin => -1, -colorigin => -2, -rowtagcommand => \&rowSub, -coltagcommand => \&colSub, -colstretchmode => 'last', -rowstretchmode => 'last', -selectmode => 'extended', -sparsearray => 0, ); my $button = $top->Button( -text => "Exit", -command => sub{ $top->des +troy}); # hideous Color definitions here: $t->tagConfigure('OddRow', -bg => 'orange', -fg => 'purple'); $t->tagConfigure('OddCol', -bg => 'brown', -fg => 'pink'); $t->colWidth( -2 => 7, -1 => 7, 1=> 5, 2 => 8, 4=> 14); $label->pack( -expand => 1, -fill => 'both'); $t->pack(-expand => 1, -fill => 'both'); $button->pack(-expand => 1, -fill => 'both'); my $cnt; sub Timer { print "Now\n"; my $variable = $t->cget( -var); $t->activate("4,0"); $t->curvalue( "Test".$cnt++ ); # NOTE # $t->curvalue( $variable->{"4,0"}="Test".$cnt++ ); # NOTE # $variable->{"4,0"}="Test".$cnt++; # $t->activate("4,0"); # use Data::Dump 'dd'; dd $variable->{"4,0"}; #$t->activate("4,0"); #$t->colWidth( -2 => 7, -1 => 7, 1=> 5, 2 => 8, 4=> 14); #$t->update(); $top->after(1000, \&Timer); return 1; } $top->after(1000, \&Timer); Tk::MainLoop;
Re: TableMatrix asynch update of cells
by Marshall (Canon) on Apr 25, 2022 at 21:03 UTC
    The reason why you see this symptom is that you are breaking OO encapsulation by modifying an object's internal storage directly without using the object's method calls for that purpose.

    $variable->{"4,0"}="Test".$cnt++; Your object, $t is oblivious to the fact that one cell just changed. And you have to use brute force to make an update of the entire window happen.

    $t->activate("4,0"); $t->curvalue( "Test".$cnt++ ); This works because $t is now fully aware that a cell within the %variable hash has changed and Tk will therefore update the screen automatically.

    Raw performance is one reason to violate OO encapsulation. I did this in one application with often say 100,000 cells. When I say sorted by a column, I manipulated $variable directly and then called one of the methods that you correctly found will cause a full window "repaint". The internal data storage for a tablematrix object is amazingly enough, not an array or an array of hashes, but a 1D hash table. The combination of row and column are the keys. $variable->{"0,2"}="something"; #sets row 0, column 2 to "something"

    Under certain circumstances, it is possible to "hide" some extra info inside the $variable which tablematrix will ignore (meaning more info than just values of the coordinates). Of course this is a massive OO encapsulation violation! I haven't needed to do that myself, but I have heard of this being done.

    In your application, just call the appropriate methods on the $t object. Do not manipulate the storage of $t directly.

    Update: Another comment, I see you have: -sparsearray => 0, in order to override the default of using a sparsearry. The effect of this could range from "nothing" to "a lot" in terms of the number of hash keys generated. In general, I would advise using the object's defaults and then enable stuff like this when needed and then put a comment in the code about why this was needed.

      Thanks for your kind responses.
      I agree that breaking OO encapsulation is a bad idea, but I don't really understand why it is described as an attribute alongside all other "public" attributes unless it is also to be regarded as a means for manipulating the table it is associated with.
      By using the "appropriate methods", I assume you mean the set method? This does work, but only as long as the TableMatrix is not disabled.
      (My supplied example does not set the TableMatrix to disabled, which is my bad, it shold have been for a clearer example.)

      (The reason for using a disabled TableMatrix is to avoid the user making changes to it, or , where applicable, replacing the cell with e.g. a Combobox widget for easier editing. The TableMatrix cells must never be changed, thus I use the -state => 'disabled')

      So, I rephrase my original question: What is the best way to update the cells of a disabled TableMatrix without breaking OO encapsulation?
      Regards

        You can try playing games with "validate" to leave the TableMatrix enabled but only allow change to the one desired cell.

        Something like this...

        #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11143267 use warnings; use Tk ':eventtypes'; use Tk::TableMatrix; use Data::Dumper qw( DumperX); my $top = MainWindow->new; my $changing = ''; my $arrayVar = {}; foreach my $row (-1..6){ foreach my $col (-2..5){ $arrayVar->{"$row,$col"} = "r$row, c$col"; } } ## Test out the use of a callback to define tags on rows and columns sub rowSub{ my $row = shift; return "OddRow" if( $row > 0 && $row % 2) } sub colSub{ my $col = shift; return "OddCol" if( $col > 0 && $col%2) ; } my $label = $top->Label(-text => "TableMatrix v1 Example"); my $t = $top->Scrolled('TableMatrix', -rows => 8, -cols => 8, -width => 6, -height => 6, -titlerows => 1, -titlecols => 2, -variable => $arrayVar, -roworigin => -1, -colorigin => -2, -rowtagcommand => \&rowSub, -coltagcommand => \&colSub, -colstretchmode => 'last', -rowstretchmode => 'last', -selectmode => 'extended', -sparsearray => 0, -validate => 1, # NOT +E -validatecommand => \&allowchange, # NOT +E ); my $button = $top->Button( -text => "Exit", -command => sub{ $top->des +troy}); # hideous Color definitions here: $t->tagConfigure('OddRow', -bg => 'orange', -fg => 'purple'); $t->tagConfigure('OddCol', -bg => 'brown', -fg => 'pink'); $t->colWidth( -2 => 7, -1 => 7, 1=> 5, 2 => 8, 4=> 14); $label->pack( -expand => 1, -fill => 'both'); $t->pack(-expand => 1, -fill => 'both'); $button->pack(-expand => 1, -fill => 'both'); sub allowchange { my ($row, $col) = @_; my $cell = "$row,$col"; return $cell eq $changing ? 1 : 0; } my $cnt; sub Timer { print "Now\n"; my $variable = $t->cget( -var); $changing = "4,0"; # NOTE $t->activate("4,0"); # NOTE $t->curvalue( "Test".$cnt++ ); # NOTE $changing = ""; # NOTE #$t->activate("4,0"); #$t->colWidth( -2 => 7, -1 => 7, 1=> 5, 2 => 8, 4=> 14); #$t->update(); $top->after(1000, \&Timer); return 1; } $top->after(1000, \&Timer); Tk::MainLoop;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11143267]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2024-03-28 18:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found