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

Dear monks,

I need to show a table in my Tk application, about 40 rows and 5 columns. I'm using Tk::Table for this task, and find it quite slower than I need. I understand that it uses a widget for each cell, so I have 200 widgets (windows) open, updating and getting messages. The Tk::Table pod warns against large tables.

But what are the alternatives ? I implemented the same using a grid packer, but there, naturally, it's the same story - cell = widget.

My last resort is to roll something with a Canvas, which should be faster (a single widget), but I don't want to get there, as it's complicated. I heard that Hlist may be of help, but I never quite thougt about it in the same way.

Any Ideas ?

Update: I tried HList. It definitely isn't what I need, appearance-wise.

Replies are listed 'Best First'.
Re: Tk::Table too slow. Alternatives ?
by zentara (Archbishop) on Jan 01, 2004 at 16:19 UTC
    I'm not exactly sure of what you are doing, but a fellow on has tried to do something like you want. Check out DynaTabFrame

    It's just a guess, but it's worth looking at. It has a screenshot and a demo.

Re: Tk::Table too slow. Alternatives ?
by pg (Canon) on Jan 01, 2004 at 22:43 UTC

    Tk::Table is slow, but I tried with 40 X 5 table, it seems "okay" to me.

    I don't know what widget you used for each cell. Some widgets are lighter than others. As you said an alternative is to draw on Canvas, I assume your table is readonly, in this case, Label is good enough for your cells. You can use Button as row and column header. (Even if your cells are writable, most likely Entry is good enough.)

    Below is the code I tried, it does take around 10 seconds to come up, but after that it responses to row or column scroll quite okay. (I think I should mention that my computer is 7 years old and really slow)

    use Tk; use Tk::Table; use Data::Dumper; use strict; my $mw = MainWindow->new; $mw->geometry("600x250"); my $table = $mw->Table(-rows => 40, -columns => 5, -scrollbars => "se", -fixedrows => 1, -fixedcolumns => 1, -takefocus => 1)->pack; foreach my $col (1 .. 5) { my $col_header = $mw->Button(-text => "Column " . $col); $table->put(0, $col, $col_header); } foreach my $row (1 .. 40) { my $row_header = $mw->Button(-text => "Row " . $row); $table->put($row, 0, $row_header); foreach my $col (1 .. 5) { my $cell = $mw->Label(-width => 10, -text => $row * $col, -bor +derwidth => 1, -relief => "solid"); $table->put($row, $col, $cell); } } MainLoop;

    I do have a thought triggered by your OP, to create something like Tk::TableLite. The biggest parts I want to improve are:

    1. instead of having one widget for each cell, only have one widget for each cell in the viewport. By doing this, the weight of the GUI, is no longer related to the size of the data, and it is predetermined.
    2. Scroll should not scroll widgets (cells), widgets are fixed. Scroll only scrolls a sliding window against the data, and the data in the sliding window will be used to reset the text displayed in cells.
      It's not terribly slow, but it's slow. I use Labels as the widgets, so it should be faster, in theory... The most annoying part is turning it off - it takes 5 seconds to close the application (hmm... sending kill messages to 200+ windows).

      Anyway, I implemented a table with a Canvas, it works nicely and is faster. I needed another Canvas for the headings though, as I wanted them to be un-scrollable.