Graphics2D.hit方法返回不符合预期的布尔值,求解决方案
解决Graphics2D hit方法返回false的问题
你的问题根源在于存储的storedG2d对象在paintComponent方法执行完毕后已经失效,用它进行命中测试会导致坐标变换逻辑异常,从而返回错误结果。另外,对于简单矩形的命中测试,根本不需要用到Graphics2D.hit()方法,直接判断点是否在矩形范围内即可。
解决方案1:直接判断点是否在矩形内
对于简单的矩形,直接使用Rectangle.contains(Point)方法就能准确判断鼠标点击是否在矩形区域内,这是最简洁高效的方式。
修改SelectListener的mousePressed方法:
class SelectListener extends MouseInputAdapter { @Override public void mousePressed(MouseEvent e) { System.out.println(e.getPoint()); System.out.println(HitTest.canvas.rectangle); // 直接判断点是否在矩形内 System.out.println(HitTest.canvas.rectangle.contains(e.getPoint())); } }
解决方案2:正确使用Graphics2D进行命中测试(针对复杂场景)
如果后续需要处理带有变换(比如缩放、旋转)的复杂图形,不能存储paintComponent中的Graphics2D对象,而是要在命中测试时创建临时的Graphics2D,并应用和绘制时相同的变换逻辑,再调用hit方法。
修改后的核心代码示例:
class CanvasArea extends JPanel { Rectangle rectangle = new Rectangle(); MouseInputAdapter mode; // 移除失效的storedG2d变量 CanvasArea() { setBackground(Color.WHITE); setPreferredSize(new Dimension(1000, 600)); } // 其他原有方法保持不变... @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; // 若有自定义变换,可在此记录变换矩阵 // AffineTransform drawTransform = g2d.getTransform(); g2d.draw(rectangle); } } class SelectListener extends MouseInputAdapter { @Override public void mousePressed(MouseEvent e) { System.out.println(e.getPoint()); System.out.println(HitTest.canvas.rectangle); // 创建临时Graphics2D进行测试 Graphics2D tempG2d = (Graphics2D) HitTest.canvas.getGraphics(); try { Rectangle mouseRect = new Rectangle(e.getPoint(), new Dimension(1, 1)); // 若绘制时有自定义变换,需先将相同变换应用到临时Graphics2D // tempG2d.setTransform(drawTransform); System.out.println(tempG2d.hit(mouseRect, HitTest.canvas.rectangle, false)); } finally { tempG2d.dispose(); // 用完必须释放资源 } } }
关键原因解释
paintComponent中的Graphics对象由Swing框架管理,方法执行完毕后框架会回收或重置其状态,存储并后续使用会导致不可预期的坐标变换或上下文错误。Graphics2D.hit()方法的第一个参数是设备空间的区域,第二个是用户空间的形状,当使用失效的Graphics2D时,它的变换矩阵可能已被修改,导致形状被错误转换,最终命中测试失败。
内容的提问来源于stack exchange,提问作者Jacky
相关产品推荐
相关产品推荐

