【问题标题】:Java, Swing: tooltip and affine transformation issueJava,Swing:工具提示和仿射变换问题
【发布时间】:2016-11-14 22:32:16
【问题描述】:

用Java编写GUI,出现了一个有趣的问题。对于略长的代码,我深表歉意。

有一个派生自 JPanel 的类 Graphic,它显示上传的栅格。它使用栅格数据实现了几个功能,包括缩放操作。它还支持鼠标单击事件,该事件存储点的坐标并将其显示在栅格上。栅格经过仿射变换拟合。

 import java.awt.*;
 import java.awt.event.*;
 import java.awt.geom.*;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.util.Locale;
 import javax.imageio.ImageIO;
 import javax.swing.*;

 public class Graphic extends JPanel{

    private BufferedImage image; 
    private AffineTransform trans;
    Point2D.Double point;

    public Graphic () {
            try {image = ImageIO.read(new File("e:/Work/test.jpg"));}
            catch (Exception e) {}
            trans = new AffineTransform();
            trans.translate(0, 0);
            trans.scale(1, 1);
            point = new Point2D.Double(0,0);
            this.setToolTipText("");

            addMouseListener(new MouseAdapter() {
                    public void mouseClicked(MouseEvent e) {
                            point.x = (e.getPoint().getX() - trans.getTranslateX()) / trans.getScaleX();
                            point.y = (e.getPoint().getY() - trans.getTranslateY()) / trans.getScaleY();
                            System.out.println(trans);  //Print affine transformation parameters
                            System.out.println(e.getPoint().getX() + " " + e.getPoint().getY()); //Cursor coordinates
                            repaint();
                    } 
            });
    }

    protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            if (image != null ){    
                    trans = g2d.getTransform();
                    Dimension size = this.getVisibleRect().getSize();
                    double sx = (size.getWidth() - image.getWidth()) / 2;
                    double sy = (size.getHeight() - image.getHeight()) / 2;
                    trans.translate(sx, sy);
                    g2d.setTransform(trans);
                    g2d.drawImage(image, 0, 0, this);        
                    g2d.fillOval((int)point.x - 10, (int)point.y - 10,  20,  20);
                    g2d.dispose();
            }
    }

    @Override
    public String getToolTipText(MouseEvent e) { 
            double x = (e.getX() - trans.getTranslateX()) / trans.getScaleX();
            double y = (e.getY() - trans.getTranslateY()) / trans.getScaleY();
            return String.format(Locale.ROOT, "%2.2f", x) + "  " + String.format(Locale.ROOT, "%3.2f", y); 
    }

    public static void main(String[] args){
            JFrame f = new JFrame();
            f.setSize(800, 600);
            f.add(new Graphic());
            f.setVisible(true);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}

该类重新定义了工具提示方法并显示光标的坐标。

在工具提示出现之前,鼠标点击图片按预期工作

Figure1: mouse click, without tool tip

一个圆圈出现在正确的位置。

Figure 2: drawn point mark, without tool tip

接下来,让我们在出现工具提示后重复这些步骤。鼠标点击图片

Figure 3: mouse click, tool tip appears

行为出人意料,点画得很远。

Figure4: drawn point mark, tool tip appeared

调试代码,发现如下问题...出现工具提示时,仿射变换中的移位比sx=mo2,sy=m12从

AffineTransform[[1.0, 0.0, -1927.5], [0.0, 1.0, -1435.1]]
379.0 339.0  //Cursor coordinates xc, yc

AffineTransform[[1.0, 0.0, -2303.5], [0.0, 1.0, -1794.5]]
376.0 339.0  //Cursor coordinates xc, yc

为了避免整个情况发生偏移,而不是 m02 和 m12 偏移,转换后的坐标 point.x,point.y 应该通过添加光标坐标 + 一些东西来更正。这是 Swing 库中的错误还是功能:-)?

非常感谢您的 cmets、帮助或解释...

光栅文件:test.jpg

【问题讨论】:

  • "剩下的代码是.." 为了尽快获得更好的帮助,请发布 one minimal reproducible example 或 @987654327 @ 而不是一堆无法编译的代码sn-ps。例如,获取图像的一种方法是热链接到此问题中嵌入的图像。
  • 我不关心你有一个贯穿始终的工具提示,并随时更改 - 现在这是一个错误还是一个功能??
  • @Andrew:由于复杂性,我无法编写更短的代码。代码已更新,可编译。它适用于任何上传的 JPG 文件。
  • “我无法编写更短的代码。” 你能开发更长的注意力范围吗? MCVE/SSCCE 不仅仅是最初的 M 或 S,请注意,如果确实需要成为 CVE/SCCE,则代码最多可以运行 200 LOC 并且仍然符合描述。现在将main(String[]) 方法复制回Graphic 类的末尾,将File更改 为指向URLURL,然后复制/ 将整个(包括导入)结果粘贴到您的 IDE 中的一个新项目中并检查它编译干净并显示问题!
  • @安德鲁:谢谢你的建议。我希望帖子更清晰,更具可读性...

标签: java swing tooltip affinetransform


【解决方案1】:

解决方案非常简单......

在存储点的坐标之前,需要调用另一个 repaint()。因此,利用了鼠标点击事件之前的鼠标按下事件:

@Override
public void mousePressed(MouseEvent e) {
    repaint();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 2010-12-17
    相关资源
    最近更新 更多