in reply to Re: Problems with Tk freezing
in thread Problems with Tk freezing

Yeah, I see you try to handle deleting objects in your code, but the sad fact is, you are overlooking something. In my experience, it is a hash key that is not getting completely removed, or you get auto-vivication in some hashes. But without actually trying to trouble shoot your code, and just from your comment " so every pixel is, unfortunately, a seperate, persistant line segment" , you need to rethink how you draw your lines, so that every pixel IS NOT a new segment.

My first thought would be to create 1 segment for each moving object. Then as it moves and consumes another pixel, reconfigure the original segment to the end points of the collective pixels. If you think about it a bit, you should be able to do this easily, especially if they move vertically.

I encountered a similar problem in Tk Realtime data aquisition, where I was adding many segments to a continuing graph, and the cpu would bog down after awhile. My solution was to use segments up to a point, then write them out as a solid non-updating curve, then start another temporary segment.

So this little project may be just too 'big' for Tk's abilities to handle??

No you are reaching a point where your desire to use straight forward programming techniques is hitting the limit, where you need to start creatively juggling. Just about any language you use, that has a canvas (and canvas items) will be the same. You cannot expect a widget to handle a gazzillion items, as effectively as a few hundred. BUT if you really insist on following your way of thinking, you might want to switch to SDL. SDL dosn't have the notion of line segments to keep track of, In SDL you write something to the screen and forget it and move on. This has advantages in situations like yours, but disadvantages in that there is no way to easily identify and manipulate an existing segment, and if it gets erased from the screen, it's gone.

Just think about an algorithm that you can feed a set of points (pixels) and it will return 2 pixels which are the extreme end points. Then use those 2 points to reconfigure the bot on the update. That way your canvas will only be handling a fixed number of lines at any one time, just making them longer thru a reconfigure. Or if you eventually want to move along curves, use the technique I showed in Tk Realtime data aquisition, and have each bot, after say 100 updates, leave the last 100 points as a solid non-updatable curve, then start another 100 pixel set which is continually updated.


I'm not really a human, but I play one on earth. Cogito ergo sum a bum

Replies are listed 'Best First'.
Re^3: Problems with Tk freezing
by wulvrine (Friar) on Feb 08, 2007 at 15:27 UTC
    Again thanks for your time and assistance.
    In the final program the lines would be walking across each other, in the end most probably changing every pixel. I thought about adding pixels together to form a line, then break it later when it is crossed. But in the end, it will probably be every pixel for himself, sitting there until it is 'walked over' and changed in color.
    Is there a way in the canvas item that would allow me to color a pixel, but immediately throw away the id string. I am only keeping them around so that I can delete them later. I just want to color the pixel, leave it that way, and move on. If a 'bot' crosses over another line, it should change the pixel to its color, and move on. I don't know of any way to do that that is 'id'less.
    Thanks for any help!!

    s&&VALKYRIE &&& print $_^q|!4 =+;' *|
      Try the Tk-Canvas-Point module, by Slaven Rezic. It is mostly a proof-of-concept trial module, and not gauranteed to do what you want. Try this sample code. It makes little circles, but that is just so you can see them, it will do a single pixel.
      #!/usr/bin/perl -w use Tk; use Tk::Canvas::Point; use strict; #adapted from Tk::CanvasPoint by Slaven Rezic my $mw = MainWindow->new; my $c = $mw->Canvas->pack(-fill => "both", -expand => 1); $c->bind("all", "<1>" => sub { my($c) = @_; my(@tags) = $c->gettags("current"); warn "Tags of current item: @tags\n"; my(@coords) = $c->coords("current"); warn "Coords of current item: @coords\n"; }); my $tag = ""; $c->bind("all", "<Enter>" => sub { my($c) = @_; $tag = ($c->gettags("current"))[0]; }); $c->bind("all", "<Leave>" => sub { my($c) = @_; $tag = ""; }); my @p; $mw->update; create_points(); $mw->update; for (1..10) { delete_last_point(); $mw->update; } postscript(0); $mw->update; my $f = $mw->Frame->pack; $mw->Button(-text => "Create points", -command => sub { create_points() } )->pack(-side => "left"); $mw->Button(-text => "Delete last point", -command => sub { delete_last_point() }, )->pack(-side => "left"); $mw->Button(-text => "PS", -command => sub { postscript(1) })->pack(-side => "left"); $mw->Label(-width => 10, -textvariable => \$tag)->pack; MainLoop; sub create_points { for(1..100) { my $width = rand(20); push @p, $c->create('point', rand($c->width),rand($c->height), -width => $width, -activefill => "white", -activewidth => $width+2, -fill => [qw(blue red green yellow black white)]->[ran +d(5)], -tags => "tag".int(rand(100)), ); } } sub delete_last_point { $c->delete(pop @p) if @p; } sub postscript { my $display = shift; my $f = "test.$$.ps"; $c->postscript(-file => $f); open(F, $f) or die $!; my($firstline) = <F>; close F; system("gv $f &") if $display; } __END__
      Otherwise, you need to go to SDL to do this. SDL just "blits" stuff to the screen, and there is no object-item associated with it. That is why it is used for games, it can be alot faster. To erase what you previously blited, you write the background color to it's location. Tk is designed to have items, that you can tag, and have mouse and key bindings to it.

      I'm not really a human, but I play one on earth. Cogito ergo sum a bum