So: how do I flush events, or make the event-buffer smaller or
whatever that will make the reaction of my interface more snappy??
I know it won't get faster, I just want to get rid of all those unnecesary
updates in between. (Like being able to say : give me the last move-event
and discard the rest)
Please help me!! *sounding desperate*
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
_/ Tako Schotanus TNO Building and Construction Research _/
_/ Phone : +31 15 842393 Fax : +31 15 122182 E-mail : s...@bouw.tno.nl _/
_/ My employer is required,by Dutch law,to disagree with whatever I say _/
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
My hunch is that the problem is in your X server, so there is not a lot
that can be done. If Tk gets behind, it collapses motion events together
to catch up. But some servers are very slow at drawing certain things,
like ovals. If this is the case, what happens is that Tk gets all the
events on time and generates a huge queue of display commands, which get
buffered up in the server. The server is very slow at redrawing, so it
takes a long time to catch up.
You might try putting an "update" command at the end of your event binding
for mouse motion. This may help by delaying the creation of more drawing
commands until all the outstanding ones have been completed; at this point
Tk will collapse together all the motion events that have collected, so
things will catch up more quickly.
Here's what you do: in your code that handles a mouse motion event, at
the very end (after it's finished moving the objects), add this one line:
update idletasks
Now, I know there are a lot of people out there who just read that and
have decided I'm completely bonkers. But it does work. Here's why:
Tk already has event compression code to remove extra mouse motion
events. So, whenever it gets a bunch of mouse events from the server,
it will only act on the last one. The problem that you're having is
that many of these mouse motion events haven't yet been delivered from
the server. The server is still working on them, or they're in the
pipe in the network.
Among other things, "update idletasks" causes Tk to call the Xlib
function XSync(). XSync sends an event to the X server and waits for
it to come back. This has the effect of forcing the X server to
generate and deliver all of those pending mouse events. So now,
they'll all be sitting in the event code, and the existing Tk event
compression code will throw most of them away. Exactly what you want.
Try it, I think you'll be pretty happy.
- Terry http://www.hal.com/services/juggle/home/weis...@sgi.com/
: So: how do I flush events, or make the event-buffer smaller or
: whatever that will make the reaction of my interface more snappy??
: I know it won't get faster, I just want to get rid of all those unnecesary
: updates in between. (Like being able to say : give me the last move-event
: and discard the rest)
You have to use a technique called "compressed motion". Use your
"bind" event handlers to catch all the motion events but don't draw
immediately. Do a redraw only when an idle event happend: example
proc motion_handler {x y} {
global mx my redrawing
set mx $x
set my $y
if {!$redrawing} {
set redrawing 1
after 0 redraw
}
}
proc redraw {} {
# redraw according to mx my
set redrawing 0
}
If you want you app to be more responsive, you can force an immediate
redraw once five times or so
Ioi
I believe J.O. and I posted our replies at the same time, so he didn't
see mine...
"update idletasks" will definitely help in the case of slow ovals.
"update idletasks" calls XSync(), which won't return until the server
has finished drawing that oval. Then you'll be able to compress
together all the mouse events that have been accumulating, so you'll
won't fall further behind.
- Terry http://www.hal.com/services/juggle/home/weis...@sgi.com/
: update idletasks
: Now, I know there are a lot of people out there who just read that and
: have decided I'm completely bonkers. But it does work. Here's why:
: Tk already has event compression code to remove extra mouse motion
: events.
According to my experience, Tk's motion compression is not
sufficient. I have to do the motion compression in my TCL code;
otherwise if I run under a slow machine and the motion event handler
needs to do a low of drawing, it will be lacking behind even if I call
"update idletasks".
Should I call "update" instead? I think not because that will
cause my event handlers to be recursed.
Ioi.
I already had an 'update idletasks' at the end of the code ('update'
alone will make everything go totaly haywire :)
Thanks anyway,
Tako
PS: Maybe this will give a clue:
If I have a lot of items on-screen (100 bitmaps + ~400 lines) and pick
some up to drag them, the response gets slower the further apart the
objects are. Of course, the more objects you pick up the slower it will
get but now you can pick up three objects close together and they move
quite quickly but you pick three objects far apart and everything slows
down incredibly. Could you (or somebody else) explain why??
At first I used a bounding box (a rectangle) to drag items but with
so many objects I was too slow. I figured that the calculations done
to find out which items would be in front of the rectangle and which in
behind were taking up most of the time. So I changed the box to 4 lines,
but they were even slower, so I changed them to 4 small lines at the
corners of the box (like small hooks). Now the response was better but
even then when the "hooks" are far apart it's MUCH slower than when
they're close together. I really don't understand why...
Any help appreciated!!
See my reply to J.O.
And thanks for the above explanation. Can you also explain maybe what
happens exactly when you do an "update"? Because if I remove the
"idletasks" everything goes bananas!
Thanks again,
Tako
"update" alone will cause Tk to check for any pending events from the
X server and to process them. That means that your mouse-event
handling routine could get called recursively. If you're not prepared
for that, things might go haywire...
> PS: Maybe this will give a clue:
>
> If I have a lot of items on-screen (100 bitmaps + ~400 lines) and pick
> some up to drag them, the response gets slower the further apart the
> objects are. Of course, the more objects you pick up the slower it will
> get but now you can pick up three objects close together and they move
> quite quickly but you pick three objects far apart and everything slows
> down incredibly. Could you (or somebody else) explain why??
>
> At first I used a bounding box (a rectangle) to drag items but with
> so many objects I was too slow. I figured that the calculations done
> to find out which items would be in front of the rectangle and which in
> behind were taking up most of the time. So I changed the box to 4 lines,
> but they were even slower, so I changed them to 4 small lines at the
> corners of the box (like small hooks). Now the response was better but
> even then when the "hooks" are far apart it's MUCH slower than when
> they're close together. I really don't understand why...
>
> Any help appreciated!!
I believe the reason this is due to the repaint algorithm of canvases.
Anytime you change something in a canvas, it remembers a single
bounding rectangle of all the changed area. Then, when it decides
everything's idle (or, incidentally, when you call "update
idletasks"), it repaints everything within that rectangle.
Your problem, of course, is that you're creating and moving your four
little hooks. The canvas sees four changes at four distant points,
and creates a bounding box holding them all. So, the farther apart
these points are, the more work it takes to repaint everything within
that bounding box.
One solution might be to call "update idletasks" after you
move/create/delete each and every one of those little hooks. Blech.
- Terry http://www.hal.com/services/juggle/home/weis...@sgi.com/
|> If I have a lot of items on-screen (100 bitmaps + ~400 lines) and pick
|> some up to drag them, the response gets slower the further apart the
|> objects are. Of course, the more objects you pick up the slower it will
|> get but now you can pick up three objects close together and they move
|> quite quickly but you pick three objects far apart and everything slows
|> down incredibly. Could you (or somebody else) explain why??
|>
|> At first I used a bounding box (a rectangle) to drag items but with
|> so many objects I was too slow. I figured that the calculations done
|> to find out which items would be in front of the rectangle and which in
|> behind were taking up most of the time. So I changed the box to 4 lines,
|> but they were even slower, so I changed them to 4 small lines at the
|> corners of the box (like small hooks). Now the response was better but
|> even then when the "hooks" are far apart it's MUCH slower than when
|> they're close together. I really don't understand why...
|>
|> Any help appreciated!!
The reason is that when the Canvas widget updates its display, it creates
one pixmap large enough to draw *all* the changed objects into, draws the
objects onto the pixmap and then copies the pixmap onto the area of the
window which needs updating.
Obviously, if you're moving objects which are far apart, a larger pixmap
will have to be allocated and copied to the screen. That's slow enough,
but all objects overlapping that pixmap will have to be drawn onto the
pixmap before blitting, and so that slows things down as well :-(
There's not much you can do to avoid the problem, unless you want to
write a new widget which avoids this problem.
Cheers,
Nat.
--
/// Nat Pryce | mail: n...@doc.ic.ac.uk, WWW: http://scorch.doc.ic.ac.uk/~np2
( oo ------------------------------------------------------------------------
|\_| It is essential to dig the most for if you do not dig you lose your
superiority over the square and so are less likely to be cool - Kerouac