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

I need to load a text file with 5,000 - 10,000 lines of text into a grid with 16 controls per row (3 text fields and 13 radio buttons), then allow the user to scroll through the data smoothly. Currently I create a grid layout and load all the rows of data at once. This works for small files (< 1000 rows), but after that the load times for creating the grid increase dramatically. (Last time it took 10 minutes to load, and scrolling was unendurably slow.)

Clearly, creating 100,000+ controls is not a scalable solution, so I will have to create a smaller grid and page through the data, swapping the bound variables constantly. And I will need to play with the scrollbar, because the bottom of the loaded data is not necessarily the bottom of all the data.

Does anyone have any Tk examples that do this? I have only used the Scrolled method to make scrollbars, and I doubt that it can handle this situation (unless you know otherwise!)

- Paul
  • Comment on Tk - Paging and scrolling through 5-10K rows of data and controls

Replies are listed 'Best First'.
Re: Tk - Paging and scrolling through 5-10K rows of data and controls
by lamprecht (Friar) on Jun 09, 2009 at 19:41 UTC
    Hi,

    maybe it would be easier to separate displaying and editing your data. Tk::Text can easily scroll through 10000 lines. You can add a highlight bar (like below) and bind a Buttonpress event to popup an edit form for the current line. I'd also add a Balloon with a message like "right-click to edit..." or something...

    use warnings; use strict; use Tk; my $mw = tkinit; my $t = $mw->Scrolled('ROText')->pack; for (1..10000){ $t->insert('end', "$_\t yes no yes no \n"); } $t = $t->Subwidget('scrolled'); $t->bindtags(['Custom',$t->bindtags]); $t->tagConfigure('Highlight', -background => 'yellow'); $t->bind('Custom','<3>',[\&edit, Ev('@')]); $t->bind('<Motion>',[\&motion, Ev('@')]); MainLoop; sub motion{ my $text = shift; my $i = $text->index($_[0]); my ($line,undef) = split (/\./,$i); $t->tagRemove('Highlight','1.0','end'); $t->tagAdd('Highlight',"$line.0",($line+1).".0"); } sub edit{ #print @_; my $text = shift; my $i = $text->index($_[0]); my ($line,undef) = split (/\./,$i); print $line,"\n"; # edit_dialog($text,$line) Tk::break; }
    Cheers, Christoph
Re: Tk - Paging and scrolling through 5-10K rows of data and controls
by graff (Chancellor) on Jun 10, 2009 at 05:21 UTC
    I have seen some Tk-based apps (not only in perl, but python as well) get bogged down because of creating way too many widgets inside other widgets. (This apparently runs contrary to Marshall's experience, but it's obviously a possible, even likely outcome.)

    So the idea in the first reply is the direction I would take, IF it's really the case that a user needs to see a bunch of adjacent lines in order to do what needs to be done manually.

    If each "row" in your text file involves a set of user decisions that are independent of the decisions made on any other row, that's an even better reason for having a separation between search/review/select activities and edit/update activities. A total of maybe 8 widgets for the former, and 20 for the latter, should give you a simple, clean, fast and easy-to-use interface.

      There are definitely some HUGE ways to go "wrong" in terms of performance with the GUI. I spent a couple of months figuring out how to make my GUI work in a very performant way. This subject is NOT easy and I hope that I didn't give an impression that it is easy, because it is not!

      I have seen some U/I things that just "drag an app into dirt".

Re: Tk - Paging and scrolling through 5-10K rows of data and controls
by Marshall (Canon) on Jun 09, 2009 at 22:41 UTC
    It would be helpful if you could show some code. Some of my Tk windows have 100,000+ objects. A display as you are describing should take <<1second not 10 minutes!
Re: Tk - Paging and scrolling through 5-10K rows of data and controls
by lamprecht (Friar) on Jun 10, 2009 at 18:08 UTC
    Hi,

    It's probably not very convenient for a user, having to choose from a list of 10000 widgets to edit some data. However, I wanted to give it a try and wrote a small example of scrolling the data instead of the widgets.(Don't know if you had that in mind). Seems to work, but I'd rather provide a set of widgets to filter the data appropriately and display only the data relevant for the editing task. (see graffs answer above)

    use warnings; use strict; use Tk; package Tk::MyScrollableEdit;
    package main; my $mw = tkinit; my @data; for (1..10000){ push @data, {label=> "entry $_", value => "value $_"}; } my $f = $mw->Frame()->pack(-expand => 1,-fill => 'both'); my $e_f = $f->MyScrollableEdit( -data => \@data )->pack( -fill => 'both', -side => 'left', -expand => 1, ); my $sb; $sb = $f->Scrollbar( -jump => 0 ); $sb->configure(-command => [$e_f, 'yview', $sb]); $sb->pack(-side => 'left', -fill => 'y'); MainLoop;
    Cheers, Christoph
      Christoph,

      I like your ideas, especially scrolling the text and leaving the controls in place. Then when the scrolling stops, I update the controls to show the values for the lines in view. That way I can get rid of 90+% of my controls!

      As for ease of use, I have been rapid prototyping and trying to find easy ways to allow the user to make these edits. To answer one question put to me above, the user must see one or two dozen lines of context to make their decisions for a single line. The decisions are join to previous line, split from previous, delete line, change text of line, identify line as a "See also", a glossary term, an index term, and identify the level of indentation (1, 2, 3 or 4). Basically I am taking semi-structured text (a book index) and adding semantic information. My parser gets most lines right, but since I am converting PDFs into text, weird things happen, the indentation gets screwed up, Unicode characters intrude, headers and footers must be discarded, etc. Thus the user must edit the semantics.

      I could just post my results in an XML text editor and let them edit it that way, but I found that to be very hard for a user to do. Reading and editing XML is painful.

      Also, directly editing the text won't work because I must store a list of change rules, not the final result. This is because I have two streams of data coming in that must be kept in synch: the text in a single column without indents but in reading order and the text in multiple columns (from which I get the indentation information that drives the computation of level.) The user edits the single column data, and I apply the edits also to the multi-columned data.

      - Paul