2

I'm currently implementing a swing JComponent as an image viewer with the ability to zoom, rotate and display the image centered and all of this animated. I have implemented all those features, but have a problem during zooming out from the right bottom corner of the image. Everytime the animation starts to stutter and only from the right or bottom edge of the panel.

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    if (this.workingCopy != null) {
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        Point2D center = new Point2D.Double((getPreferredSize().width) / 2, (getPreferredSize().height) / 2);
        g2d.scale(getZoom(), getZoom());
        g2d.rotate(Math.toRadians(getRotation()), (center.getX() + 0) / getZoom(), (center.getY() + 0) / getZoom());
        g2d.drawImage(this.workingCopy,
                (int) Math.round(((getPreferredSize().width - (image.getWidth() * getZoom())) / 2) / getZoom()),
                (int) Math.round(((getPreferredSize().height - (image.getHeight() * getZoom())) / 2) / getZoom()), null);
    }
}

public synchronized void setZoom(final double zoom, boolean animated, final Point point) {
    final double oldZoom = getZoom();

    final Dimension viewSize = getPreferredSize();
    final Rectangle viewRect = getVisibleRect();

    // get relative point
    double relX = viewRect.getX() / viewSize.getWidth();
    double relY = viewRect.getY() / viewSize.getHeight();

    // new size
    double newViewSizeWidth = (getImageBounds().getWidth() / oldZoom) * zoom;
    double newViewSizeHeight = (getImageBounds().getHeight() / oldZoom) * zoom;


    double deltaDiffX = (point.getX() - viewRect.getX()) / viewSize.getWidth();
    double deltaDiffY = (point.getY() - viewRect.getY()) / viewSize.getHeight();

    double newDiffX = newViewSizeWidth * deltaDiffX;
    double newDiffY = newViewSizeHeight * deltaDiffY;

    double viewPositionX = (newViewSizeWidth * relX) + newDiffX - (point.getX() - viewRect.getX());
    double viewPositionY = (newViewSizeHeight * relY) + newDiffY - (point.getY() - viewRect.getY());

    final Point newPoint = new Point((int) Math.round(viewPositionX), (int) Math.round(viewPositionY));

    if (animated && !zooming) {

        Animator animator = new Animator(getAnimationSpeed(), new TimingTargetAdapter() {

            @Override
            public void begin() {
                super.begin();
                zooming = true;
            }

            @Override
            public void timingEvent(final float fraction) {
                super.timingEvent(fraction);
                double zoomDiff = zoom - oldZoom;
                setZoom(oldZoom + (fraction * zoomDiff),
                        new Point(
                        (int) Math.round(viewRect.getX() - (viewRect.getX() - newPoint.getX()) * fraction),
                        (int) Math.round(viewRect.getY() - (viewRect.getY() - newPoint.getY()) * fraction)));
            }

            @Override
            public void end() {
                super.end();
                zooming = false;
            }
        });
        animator.start();
    } else {
        setZoom(zoom, newPoint);
    }
}

Can someone point out what I do I do wrong or forget to concider for the zoom animation ? Everything works except the the stuttering during the animated zoom out.

Thanks in advance for your help.

  • 3
    for better help sooner pease edit your question with a [SSCCE](http://sscce.org/) – mKorbel Mar 25 '12 at 18:12
  • Corners are always a problem. A [`FauxImage`](http://stackoverflow.com/a/8090328/230513) may be useful in creating youe [sscce](http://sscce.org/). – trashgod Mar 25 '12 at 19:02
  • I have a workaround, but still it would be nice to know whether there is a better way to solve the problem. I introduced internal variables 'width' and 'height' and added 250px to the preferred size as a buffer zone. Furthermore I restricted the scrollToVisibleRect method of the component and check with every transform and update whether the visible rect doesn't display the part of the buffer zone. – user1291485 Mar 25 '12 at 19:17
  • @user1291485 by your code posted maybe here isn't any suggestion about better way for you – mKorbel Mar 25 '12 at 19:57

1 Answers1

1

Ok, I found the problem by chance. The problem was the JPanel still had a LayoutManager and this caused the problem when zooming out from the right/bottom corner. After I set the LayoutManager to null, everything worked how it should.