简体   繁体   English

在面板内放大和缩小

[英]Zooming in and zooming out within a panel

I have a Panel in which some 2D objects are moving about.我有一个面板,其中一些 2D 对象正在移动。 I have overridden paintComponent() as necessary.我已经根据需要覆盖了paintComponent()。 Now I want to be able to zoom in and zoom out that area.现在我希望能够放大和缩小该区域。 When zooming in, scrollbars will appear by which one can view the entire field by scrolling.放大时,会出现滚动条,您可以通过滚动条查看整个字段。 While zooming in and out, the 2D objects should increase or decrease in size accordingly.放大和缩小时,2D 对象的大小应相应增加或减小。 Which Swing component or rather combination of components will help to achieve this?哪个 Swing 组件或组件组合将有助于实现这一目标?

Easiest way is to modify your panel and introduce a double indicating your zoom level.最简单的方法是修改您的面板并引入一个双倍指示您的缩放级别。 This double would indicate your scale, where 1 is normal and higher is zoomed in. You can use that double together with Graphics2D in your paintComponent .这个 double 将指示您的比例,其中 1 是正常的,放大的是更高的。您可以在您的paintComponent中将该 double 与Graphics2D一起使用。

Such as:如:

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);

For the scrolling, put your panel in a JScrollPane and combine that with a getPreferredSize that also uses your zoom scale.对于滚动,将面板放在 JScrollPane 中,并将其与也使用缩放比例的 getPreferredSize 结合起来。 JScrollPane uses the preferred size of the component you put in it. JScrollPane 使用您放入其中的组件的首选大小。 It will show scrollbars if the preferred size exceeds its own size.如果首选大小超过其自身大小,它将显示滚动条。

If you change the preferred size of your panel so that the width and height it returns is scaled you should be fine.如果您更改面板的首选大小,以便缩放它返回的宽度和高度,那么您应该没问题。 Basically you can just return something like:基本上你可以返回类似的东西:

return new Dimension(w * scale, h * scale)

I know this question is old, but I thought I could post my solution in case it could be useful for someone in the future.我知道这个问题很老,但我想我可以发布我的解决方案,以防将来对某人有用。

So, I created a class that extends JPanel which implements the MouseWheelListener in order to detect when the user rolls the mouse.因此,我创建了一个 class 扩展了 JPanel,它实现了 MouseWheelListener 以便检测用户何时滚动鼠标。 My class also listens for dragging in order to move the contents when the user clicks and drags.我的 class 还监听拖动,以便在用户单击和拖动时移动内容。

Code Explanation代码说明

First, in the constructor you must set this as the MouseWheelListener首先,在构造函数中,您必须将其设置为 MouseWheelListener

 addMouseWheelListener(this);

For the zoom in and out I used a boolean zoomer (to indicate when the user rolls with the mouse) and two doubles zoomFactor (to keep the current factor by which the objects' sizes are multiplied) and prevZoomFactor (for the previous zoom factor).对于放大和缩小,我使用了zoomer (以指示用户何时用鼠标滚动)和两个双倍zoomFactor (以保持对象大小相乘的当前因子)和prevZoomFactor (用于前一个缩放因子) .

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

I also override the paint() method of the JPanel, in which (before drawing anything) when the user zooms ( zoomer =true) I scale the graphics by the zoomFactor .我还覆盖了 JPanel 的paint()方法,其中(在绘制任何东西之前)当用户缩放时( zoomer =true)我通过zoomFactor缩放图形。 Code:代码:

@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
}

Finally, I override the mouseWheelMoved method of the MouseWheelListener, in which I increase the zoomFactor (if the user rolls up) or decrease the zoomFactor (if the user rolls down).最后,我重写了 MouseWheelListener 的mouseWheelMoved方法,在该方法中我增加了zoomFactor (如果用户向上滚动)或减少zoomFactor (如果用户向下滚动)。 Code:代码:

@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();
    }
}

Working Example工作示例

If you also want to use the drag function and want to zoom according to the position of the mouse, you can use the class below, which gets a BufferedImage as a parameter in the constructor in order to display something on screen.如果你也想使用拖拽 function 并想根据鼠标的 position 进行缩放,可以使用下面的 class 构造函数,它会在构造函数中得到一个 BufferedImage 作为参数显示在屏幕上。

I have also uploaded a project on GitHub called Zoomable-Java-Panel in which there is a functional example of what I showed above, which you can test and see how it can be implemented into a project.我还在 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) {

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM