使用 JFrame 和 AffineTransform 进行缩放和鼠标单击

问题描述 投票:0回答:1

当显示 BufferedImage 并设置相对于缩放比例的鼠标单击位置时,我遇到了鼠标单击与 JFrame 位置相关联的问题。

(代码来自此论坛:在面板内放大和缩小

`

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);
        totalZoom *=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;
        }

    }

} }`

我尝试通过使用数学来更改鼠标单击位置,但我很难正确地做到这一点。

@Override
    public void mouseClicked(MouseEvent me) {
        double x = MouseInfo.getPointerInfo().getLocation().getX() - getLocationOnScreen().getX();
        double y = MouseInfo.getPointerInfo().getLocation().getY() - getLocationOnScreen().getY();

        try {
            CommandFromClient clientSubmission= new CommandFromClient(CommandFromClient.GETBOARD);
            os.writeObject(clientSubmission);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.println("x: " + getLocationOnScreen().getX()/zoomFactor + "y: " + getLocationOnScreen().getY()/zoomFactor);

        Point clicked = new Point((int)((me.getPoint().x*10-x)),(int)((me.getPoint().y*10-y)));
        System.out.println(1f/zoomFactor);
        System.out.println("CLICK DETECTED: " + clicked);
        for(int i = yellow.size()-1;i>=0;i--) {
            Rectangle bounds = new Rectangle(yellow.get(i).getX(),yellow.get(i).getY(),yellow.get(i).getImg().getWidth(),yellow.get(i).getImg().getHeight());
            System.out.print("checks");
            if(bounds.contains(clicked)){
                System.out.print("collided");
                System.out.print(yellow.get(i));
                break;
            }
        }
    }
java jframe display affinetransform
1个回答
0
投票

如果您正在查找已通过同一系列仿射变换进行变换的鼠标单击位置,那么您可以保存要应用于图像的当前仿射变换,然后将其应用于该点。为此,请在面板类中创建一个 AffineTransformation 变量,

private AffineTransform currentTransform = new AffineTransform();

然后您的绘制方法将被更新以将仿射变换保存到该变量。该方法如下所示,并注释了更新的位:

@Override
public void paintComponent(Graphics g) {

    Graphics2D g2d = (Graphics2D) g;
    //if zoomer or dragger is true, this means that a new affine transformation is going to be made, so the currentTransform is reset
    if (zoomer || dragger) {
        currentTransform = new AffineTransform();
    }
    //if neither zoomer or dragger is true, then the graphics object will have no affine transformation to apply to the shapes on screen, so it will temporarily reset the screen
    //this line counteracts that, applying the current transformation to the shapes so they maintain their location on screen
    else {
        g2d.transform(currentTransform);
    }
    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;
        currentTransform.concatenate(at);//adds the calculated zoom transformation to the current transformation
        g2d.transform(at);
        zoomer = false;
    }
    
    if (dragger) {
        AffineTransform at = new AffineTransform();
        at.translate(xOffset + xDiff, yOffset + yDiff);
        at.scale(zoomFactor, zoomFactor);
        currentTransform.concatenate(at);//adds the dragger transformation so the current transformation is now a combination of the zoom and drag transformation
        g2d.transform(at);

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

    }

    g2d.fillRect(0,0,200,200);
    
    g2d.drawImage(image, 0, 0, this);
}

最后,我们可以在单击发生时将保存的仿射变换应用到鼠标点:

public void mouseClicked(MouseEvent me) {
    Point2D mousePoint = currentTransform.transform(me.getPoint(), null);
    System.out.println(mousePoint);
    repaint();
}

让我知道这是否是您正在寻找的内容,您的措辞让我有点困惑,但我想我明白了。

© www.soinside.com 2019 - 2024. All rights reserved.