Thursday, May 5, 2011

Animation with QTimeline

I'm using QGraphics objects to display boxes with arrows between them. I want animation on those arrows/lines that starts at one end and goes to the other.

The animation works great when the start and end locations of the arrow don't change during QTimeLine execution, i.e. I leave the view static. But since the user can drag the boxes around (and thus I redraw the arrows to follow) I need to reset the start and end position inside the QGraphicsItemAnimation so the animation matches the new arrow line.

I tried to update the start and end locations in the paint method of the Arrow object but that just makes the animation go crazy (it flips randomly all over the place). I assume it's because I changed the animation positions when the QTimeLine object was in the RUNNING state.

void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
   ...
    ///update the arrow to have a new source and destination, draw arrow, etc
   ...

    if (mAnimate)
    {
        mAnimationObj->setPosAt(0, mSourcePoint);
        mAnimationObj->setPosAt(1, mDestPoint);   
    }
}

How should I dynamically change the QGraphicsItemAnimation start and end positions (0 and 1)?

For the end product, I want the user to be able to drag the boxes around, have the arrows follow (which currently works) as well as have the animation continue along the new arrow route.

If that isn't possible, then I need to figure out some way to capture the dragging and stop the arrow animation until the user releases and then I guess reset it...?

From stackoverflow
  • I guess you just need to make a generic animation, i.e. use QTimeLine to animate between 0.0 and 1.0. From its currentValue, do the interpolation (by yourself) to find out where the animated object need to be placed. For example, for a value of 0.5, the object should be positioned halfway between the start and end positions.

    Note that this tweening trick does not work if the distance between start and end positions keep changing. You might cause the animated object to bounce back and forward in the middle of animation. One trick to do this is to keep the distance between the animated object position and the start position, then do not push back the object if the interpolated distance for the current time is less than the previous one. There are more complicated techniques for inbetweening of moving start and end points, but I won't elaborate more about it here, unless it is necessary.

0 comments:

Post a Comment