Zoomen in JPanel (AffineTransform?)

shocking

Mitglied
Hi Leute,

ich weiß zu diesem Thema sind schon zig Einträge vorhanden, aber leider hat mir keiner davon wirklich weitergeholfen... Mittlerweile bin ich echt verzweifelt über meinem Code.

Ich habe ein JPanel, welches als ViewPort in einer JScrollPane liegt. Dieses möchte ich nun zoomen.
Das Panel enthält kein Image sondern mehrere Objekte (JLabel) welche sich entsprechend ihrer Vorgaben zeichnen.

Das Zoomen funktioniert grundsätzlich. Es ist nur so, dass der Inhalt des Panels dabei optisch von oben links nach unten rechts größer wird. Ich brauche aber ein Zoom aus der Mitte heraus.
Ich habe es mit AffineTransform versucht, aber dann ist das Problem, dass die ScrollPane nicht korrekt ist (ich kann dann nicht bis zum Außenrand scrollen).

Vielleicht kann mir einer von Euch nen Tip geben?

Hier mein Code für das funktionierende Zoomen (von oben links):

Code:
package de.zoomPanel.test;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Point2D;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * Panel for displaying <code>PaintObject</code>s.
 * 
 * 
 */
public class PaintObjectsPanel extends JPanel {

    /** Generated serial version id. */
    private static final long serialVersionUID = 1986098489239427657L;

    /** Constant for default size height. */
    private static final int DEFAULT_SIZE_HEIGHT = 128;

    /** Constant for default size width. */
    private static final int DEFAULT_SIZE_WIDTH = 970;

    /** Constant for some white space between objects and panel border. */
    private static final int SOME_WHITE_SPACE = 20;

    /** Constant for default maximal location value in pixel. */
    private static final double DEFAULT_MAX_LOCATION = 1000;

    /** Default zoom value. */
    private double defaultZoom = 1.0;

    /** Current zoom factor. */
    private double zoomFactor = 1.0;

    /** Current zoom step. */
    private double zoomStep = 0.1;

    /** Background color of panel. */
    private Color backgroundColor = new Color(235, 235, 235);

    /** Initial size of content panel (with zoom). */
    private Dimension initialSize = new Dimension();

    /** Delay for repaint. */
    private int repaintDelay = 100;

    /** Instance of <code>JScrollPane</code>. */
    private JScrollPane scrollPane;

    /** List of <code>PaintObject</code>s. */
    private List<PaintObject> paintObjects;


    /**
     * Constructor.
     * 
     * @param image
     * @param zoomPercentage
     */
    public PaintObjectsPanel(double zoomPercentage) {
        zoomFactor = zoomPercentage / 100;

        this.initialSize = new Dimension(DEFAULT_SIZE_WIDTH,
                DEFAULT_SIZE_HEIGHT);

        this.setLayout(null);
    }

    public void setInitialSize(Dimension size) {
        this.initialSize = size;
    }

    /**
     * Initializes panel.
     */
    public void init() {
        Container parent = this.getParent();

        if (parent != null) {
            Container parentsParent = parent.getParent();
            if (parentsParent != null
                    && parentsParent instanceof JScrollPane) {
                this.scrollPane = (JScrollPane) parentsParent;
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.swing.JComponent#getPreferredSize()
     */
    @Override
    public Dimension getPreferredSize() {

        Dimension size = new Dimension();

        size.width = (int) (initialSize.getWidth() + (initialSize.getWidth() * (this.zoomFactor - 1)));
        size.height = (int) (initialSize.getHeight() + (initialSize.getHeight() * (this.zoomFactor - 1)));

        repaint();
        return size;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    @Override
    public void paintComponent(Graphics grp) {
        super.paintComponent(grp);
        
        Graphics2D g2D = (Graphics2D) grp;

        // Set the current color to defined background color.
        g2D.setColor(this.backgroundColor);
        // Fill the background rectangle.
        g2D.fillRect(0, 0, getWidth(), getHeight());

        // // Scale the graphics to get the zoom effect.
         g2D.scale(this.zoomFactor, this.zoomFactor);

    }

    /**
     * Resets zooming to original size.
     */
    public void zoomOriginal() {
        zoomFactor = defaultZoom;
        revalidate();
    }

    /**
     * Performs zoom in (increases zoom factor).
     */
    public void zoomIn() {
        double newZoomFactor = this.zoomFactor + this.zoomStep;
        BigDecimal myDec = new BigDecimal(newZoomFactor);
        myDec = myDec.setScale(2, BigDecimal.ROUND_HALF_UP);
        newZoomFactor = myDec.doubleValue();

        this.zoomFactor = newZoomFactor;

        revalidate();
    }

    /**
     * Performs zoom out (decreases zoom factor).
     */
    public void zoomOut() {
        double newZoomFactor = this.zoomFactor - this.zoomStep;
        BigDecimal myDec = new BigDecimal(newZoomFactor);
        myDec = myDec.setScale(2, BigDecimal.ROUND_HALF_UP);
        newZoomFactor = myDec.doubleValue();

        if (newZoomFactor >= this.defaultZoom) {
            this.zoomFactor = newZoomFactor;
        }

        revalidate();
    }

    /**
     * Returns current zoom percentage.
     * 
     * @return current zoom percentage.
     */
    public double getZoomedTo() {
        return this.zoomFactor * 100;
    }

    /**
     * Adds given <code>PaintObject</code> to list of
     * <code>PaintObject</code>s and to content.
     * 
     * @param po
     *            <code>PaintObject</code> to be added.
     * @param location
     *            where to add <code>PaintObject</code> in layout.
     */
    public void addPaintObject(PaintObject po, Point location) {

        if (this.paintObjects == null) {
            this.paintObjects = new ArrayList<PaintObject>();
        }

        if (po != null) {
            this.add((Component) po);
            this.paintObjects.add(po);

            Dimension poPrefSize = ((Component) po).getPreferredSize();

            po.setBounds(location.x, location.y, poPrefSize.width,
                    poPrefSize.height);

            Dimension size = getPreferredSize();
            if (location.x + poPrefSize.width + SOME_WHITE_SPACE > size.width) {
                int diff = (location.x + poPrefSize.width + SOME_WHITE_SPACE)
                        - size.width;
                size.width += diff;
            }

            if (location.y + poPrefSize.height + SOME_WHITE_SPACE > size.height) {
                int diff = (location.y + poPrefSize.height + SOME_WHITE_SPACE)
                        - size.height;
                size.height += diff;
            }

            setInitialSize(size);
        }

    }

    /**
     * Removes given <code>PaintObject</code> from content and list.
     * 
     * @param po
     *            <code>PaintObject</code> to be removed.
     */
    public void removePaintObject(PaintObject po) {
        this.remove(po);
        this.paintObjects.remove(po);
    }

    /**
     * Removes all <code>PaintObject</code>s from content and list.
     */
    public void removeAllPaintObjects() {
        if (paintObjects != null) {
            for (PaintObject po : paintObjects) {
                this.remove((Component) po);
            }

            paintObjects.clear();
        }

        repaint();
    }

    /**
     * 
     * @return <code>PaintObjects</code> on panel.
     */
    public List<PaintObject> getPaintObjectsOnPanel() {
        return this.paintObjects;
    }
}
 
Hallo!
Das Problem kenne ich, habe es damals aber nur teilweise gelöst bekommen.
Als Alternative zum Selbermachen gäbe es noch das Piccolo2D Framework, welches Zoomen unterstützt. Vielleicht hilft dir das weiter.
mfg flo
 
Ok, mir ist noch etwas eingefallen. Ich hab es damals hinbekommen zu zoomen und es hat auch "aus der Mitte heraus" gezommt - sonlange der Zoomfaktor größer als eins war. Darunter gabs Fehler.
Realisiert hab ich das so, dass ich mir vor dem Zoomen die Koordinaten der Mitte geholt habe, dann hab ich gezoomt und anschließend hab ich diese Koordinaten wieder für die Mitte gesetzt.
Könnte sein dass ich irgendwo noch den Code davon hab, kann ich aber erst heute Abend nachschauen...
mfg flo
 
Hi Flo,

So etwas in der Art habe ich auch versucht, habe aber auch über ZoomFaktor 1 immer irgendwelche Probleme. Entweder die ScrollBars gehen nicht mit, so dass man nicht mehr zum Außenrand scrollen kann, oder der Inhalt wird fehlerhaft verschoben... Langsam bin ich echt am verzweifeln.

In jedem Fall vielen Dank für deine Mühe, vielleicht hilft mir dein Code ja weiter, wo mein Fehler liegt...

cu shocking
 

Neue Beiträge

Zurück