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

Is there a maximum number of points permitted in a single line in Tk::Canvas? If there is, is there some way to change it?

When I try to plot a line with more than 1048572 points, my script exits. The exit occurs after the callback containing the createLine call returns. Sometimes, I get the message

X connection to :2.0 broken (explicit kill or server shutdown).

on exit, sometimes not. It isn't a maximum number of points in the canvas; I can plot many lines of 1048572 points, but no lines of 1048573 points. Note that 1048572 is very close to 1024*1024 (2^10 or 1048576), but I couldn't find either number anywhere in the Perl::Tk source. Here is an example script to show the problem. I am running under Solaris 5.10 on a SPARC Enterprise M5000, displaying on a SunRay 2FS. Perl version is 5.8.8, Perl::Tk is 804.028, all compiled under the Sun Studio 11 compiler, 64 bit.

use Tk; use strict; use warnings; my ($wf_canvas, $wid); my $mw = MainWindow->new; $mw->geometry("600x300+10+10"); my $menubar_frame = $mw->Frame(-relief => 'ridge', -borderwidth => 2) ->pack(-side => 'top', -anchor => 'n', -fill => 'x'); my $plot1_button = $menubar_frame->Button( -command => [\&plotwave1], -text => 'Plot short') ->pack(-side => 'left'); my $plot2_button = $menubar_frame->Button( -command => [\&plotwave2], -text => 'Plot long') ->pack(-side => 'left'); my $exit_button = $menubar_frame->Button( -command => sub {$mw->destroy}, -text => 'Exit') ->pack(-side => 'left'); MainLoop; exit; sub wfplot_canvas() { if (! Exists($wf_canvas)) { $wf_canvas = $mw->Canvas(-background => 'white'); $wf_canvas->pack(-expand => 1, -fill => 'both', -side => 'left'); } } sub plotwave($) { my $len = shift; my $xscale = $mw->width() / $len; my @xy = (); my $i; foreach $i (0 .. ($len - 1)) { push @xy, $i * $xscale, 100 - sin(0.00001 * $i) * 100; } $wid = $wf_canvas->createLine(@xy, -fill => 'black', -joinstyle => ' +bevel'); my @bbox = $wf_canvas->bbox('all'); $wf_canvas->configure(-height => ($bbox[3] - $bbox[1]), -width => ($bbox[2] - $bbox[0])); return; } sub plotwave1() { wfplot_canvas() if ! Exists($wf_canvas); $wf_canvas->delete($wid) if $wid; plotwave(1048572); } sub plotwave2() { wfplot_canvas() if ! Exists($wf_canvas); $wf_canvas->delete($wid) if $wid; plotwave(1048573); }

Replies are listed 'Best First'.
Re: Tk::Canvas->createLine max?
by bluescreen (Friar) on Aug 11, 2010 at 02:40 UTC

    On Tk's internal function definition pTk/mTk/generic/tkCanvLine.c number of points is referenced as int so it should support 2^32 points.

    In my netbook (linux-32 + Tk 804.029 + Perl v5.10.1) your code works out of the box, are you sure you are not running out of memory?

      Thanks for the reply! I don't think it's a memory problem because it's a 64-bit machine, OS and Perl, and has 128G of memory installed. My stop-gap fix was to limit plotting to one less than the number that causes the exit, and I am able to plot 100 of those shorter lines, but not even one line that has one more sample. But your perl and Tk are both more recent versions than mine, and that might be part of it.

Re: Tk::Canvas->createLine max?
by zentara (Cardinal) on Aug 11, 2010 at 12:37 UTC
    Hi, I think you are just running into an internal Tk wall, where it cannot handle updating too many objects. My only suggestion is to consolidate your points into mini-bezier line segments, to reduce the number of canvas objects being tracked. I used this approach in Tk Realtime data aquisition where I break every 1000 points into a new bezier segment. This greatly reduces Tk's internal overhead, by reducing it's internal object count by 1000.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku

      Thanks for the reply! This is a good plan. I was thinking that one answer might be to break up the lines, but I was uncertain how to proceed beyond just splitting the lines up into segments and plotting them adjacent to each other. I took a quick look at the script you referred me to, and it bears similarity to what I am trying to do. I have a database of time-series data from instrumentation, and I am just trying to get the data displayed. Sometimes, these series are quite long and that was where I was getting into trouble. If it is an internal Tk wall, then splitting up the lines is really the only option. Besides, reducing internal overhead would be a very good thing, since my actual script, as it stands, performs kinda slow.

Re: Tk::Canvas->createLine max?
by Khen1950fx (Canon) on Aug 11, 2010 at 06:43 UTC
    I couldn't get your script to work. The window would come up, but when I clicked on a button, it stuck. This reminds me a little of a demo called plop.ppl. It gives a good example of how to do minimum and maximum.