Увеличение и уменьшение масштаба на панели - PullRequest
13 голосов
/ 01 июля 2011

У меня есть панель, в которой движутся некоторые 2D-объекты.Я переопределил paintComponent () по мере необходимости.Теперь я хочу иметь возможность увеличивать и уменьшать эту область.При увеличении появятся полосы прокрутки, по которым можно прокручивать все поле.При увеличении и уменьшении 2D-объекты должны соответственно увеличиваться или уменьшаться в размере.Какой компонент Swing или, скорее, комбинация компонентов поможет достичь этого?

Ответы [ 2 ]

14 голосов
/ 01 июля 2011

Самый простой способ - изменить панель и ввести двойное значение, указывающее уровень масштабирования. Это двойное число будет означать вашу шкалу, где 1 - нормальное, а большее - увеличенное. Вы можете использовать это двойное число вместе с Graphics2D в вашем paintComponent.

Например:

Graphics2D g2 = (Graphics2D) g;
int w = // real width of canvas
int h = // real height of canvas
// Translate used to make sure scale is centered
g2.translate(w/2, h/2);
g2.scale(scale, scale);
g2.translate(-w/2, -h/2);

Для прокрутки поместите панель в JScrollPane и объедините ее с getPreferredSize, который также использует ваш масштаб. JScrollPane использует предпочитаемый размер компонента, который вы в него помещаете. Он покажет полосы прокрутки, если предпочтительный размер превышает его собственный размер.

Если вы измените предпочтительный размер вашей панели так, чтобы ширина и высота, которую она возвращает, масштабировалась, у вас все будет в порядке. По сути, вы можете просто вернуть что-то вроде:

return new Dimension(w * scale, h * scale)
2 голосов
/ 22 февраля 2018

Я знаю, что этот вопрос старый, но я подумал, что смогу опубликовать свое решение на случай, если оно может пригодиться кому-то в будущем.

Итак, я создал класс, расширяющий JPanel, который реализует MouseWheelListener вЧтобы определить, когда пользователь катит мышь.Мой класс также слушает перетаскивание, чтобы перемещать содержимое, когда пользователь щелкает и перетаскивает.

Код Объяснение

Сначала в конструкторе вы должны установить его как MouseWheelListener

 addMouseWheelListener(this);

Для увеличения и уменьшения я использовал логическое значение zoomer (чтобы указать, когда пользователь катится с помощью мыши) и два двойных значения zoomFactor (чтобы сохранить текущий коэффициент, на который умножаются размеры объектов) иprevZoomFactor (для предыдущего коэффициента масштабирования).

private double zoomFactor = 1;
private double prevZoomFactor = 1;
private boolean zoomer;

Я также переопределяю метод JPanel paint(), в котором (до рисования чего-либо) пользователь увеличивает (zoomer = true)Я масштабирую графику по zoomFactor.Код:

@Override
public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2 = (Graphics2D) g;
    if (zoomer) {
        AffineTransform at = new AffineTransform();
        at.scale(zoomFactor, zoomFactor);
        prevZoomFactor = zoomFactor;
        g2.transform(at);
        zoomer = false;
    }
    // All drawings go here
}

Наконец, я переопределяю метод mouseWheelMoved MouseWheelListener, в котором я увеличиваю zoomFactor (если пользователь свернется) или уменьшаю zoomFactor (если пользователь катитсявниз).Код:

@Override
public void mouseWheelMoved(MouseWheelEvent e) {
    zoomer = true;
    //Zoom in
    if (e.getWheelRotation() < 0) {
        zoomFactor *= 1.1;
        repaint();
    }
    //Zoom out
    if (e.getWheelRotation() > 0) {
        zoomFactor /= 1.1;
        repaint();
    }
}

Рабочий пример

Если вы также хотите использовать функцию перетаскивания и хотите масштабировать в соответствии с положением мыши, вы можете использовать класс ниже,который получает BufferedImage в качестве параметра в конструкторе для отображения чего-либо на экране.

Я также загрузил проект на GitHub с именем Zoomable-Java-Panel в котором есть функциональный пример того, что я показал выше, который вы можете протестировать и увидеть, как это может быть реализовано в проекте.

package zoomable.panel;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;

/**
 *
 * @author Thanasis1101
 * @version 1.0
 */
public class MainPanel extends JPanel implements MouseWheelListener, MouseListener, MouseMotionListener {

    private final BufferedImage image;

    private double zoomFactor = 1;
    private double prevZoomFactor = 1;
    private boolean zoomer;
    private boolean dragger;
    private boolean released;
    private double xOffset = 0;
    private double yOffset = 0;
    private int xDiff;
    private int yDiff;
    private Point startPoint;

    public MainPanel(BufferedImage image) {

        this.image = image;
        initComponent();

    }

    private void initComponent() {
        addMouseWheelListener(this);
        addMouseMotionListener(this);
        addMouseListener(this);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2 = (Graphics2D) g;

        if (zoomer) {
            AffineTransform at = new AffineTransform();

            double xRel = MouseInfo.getPointerInfo().getLocation().getX() - getLocationOnScreen().getX();
            double yRel = MouseInfo.getPointerInfo().getLocation().getY() - getLocationOnScreen().getY();

            double zoomDiv = zoomFactor / prevZoomFactor;

            xOffset = (zoomDiv) * (xOffset) + (1 - zoomDiv) * xRel;
            yOffset = (zoomDiv) * (yOffset) + (1 - zoomDiv) * yRel;

            at.translate(xOffset, yOffset);
            at.scale(zoomFactor, zoomFactor);
            prevZoomFactor = zoomFactor;
            g2.transform(at);
            zoomer = false;
        }

        if (dragger) {
            AffineTransform at = new AffineTransform();
            at.translate(xOffset + xDiff, yOffset + yDiff);
            at.scale(zoomFactor, zoomFactor);
            g2.transform(at);

            if (released) {
                xOffset += xDiff;
                yOffset += yDiff;
                dragger = false;
            }

        }

        // All drawings go here

        g2.drawImage(image, 0, 0, this);

    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {

        zoomer = true;

        //Zoom in
        if (e.getWheelRotation() < 0) {
            zoomFactor *= 1.1;
            repaint();
        }
        //Zoom out
        if (e.getWheelRotation() > 0) {
            zoomFactor /= 1.1;
            repaint();
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        Point curPoint = e.getLocationOnScreen();
        xDiff = curPoint.x - startPoint.x;
        yDiff = curPoint.y - startPoint.y;

        dragger = true;
        repaint();

    }

    @Override
    public void mouseMoved(MouseEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {
        released = false;
        startPoint = MouseInfo.getPointerInfo().getLocation();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        released = true;
        repaint();
    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

}
...