プログラマメモ2 - programmer no memo2

AffineTransformにはinverseTransformなるメソッドがありまして。 2008/09/16

Graphics2Dを使って画面に描画した《もの》をマウスイベントをひろってその《もの》選択するようなアプリケーション作成したい場合、
そのコンポーネントのpaintとマウスイベントを素直に使う分には、MouseEventgetX(),MouseEventgetY()で、
描画位置が対になっているのでさほど苦労せず簡単に対応できます。

つぎにこの《もの》をAffineTransformを使って描画した場合、はて、どうしたものだろうと頭をひねっていたら、
AffineTransformにはinverseTransformなるメソッドがあることに気がつきます。

僕ははじめマウス変換をかけて表示したものとMouseEventgetX(),MouseEventgetY()対応させようと考えていたのですが、
発想を変えてMouseEventgetX(),MouseEventgetY()を逆変換かけて、
AffineTransformする前の《もの》と比較すればよいわけです。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test_AffineTransform_inverseTransform {

public static void main(String[] args) {

JFrame frame = new JFrame();
JPanel panel = new JPanel() {
MouseEvent mouseEvent;
boolean isPressed = false;
{
addMouseListener(new MouseAdapter() {

@Override
public void mousePressed(MouseEvent e) {
isPressed = true;
mouseEvent = e;
repaint();
}

@Override
public void mouseReleased(MouseEvent e) {
isPressed = false;
mouseEvent = null;
repaint();
}

});
}

@Override
protected void paintComponent(Graphics g) {

Graphics2D g2d = (Graphics2D) g;

Rectangle rectangle = new Rectangle(30, 30, 70, 100);

AffineTransform affineTransform = new AffineTransform();
affineTransform.setToRotation(Math.toRadians(45));
affineTransform.translate(100, 0);
affineTransform.shear(0.2, 0.2);
g2d.setTransform(affineTransform);
//
g2d.setColor(Color.BLACK);
if (isPressed) {
if (mouseEvent != null) {

try {
Point2D p = affineTransform.inverseTransform(
new Point2D.Double(mouseEvent.getX(),
mouseEvent.getY()), null);
if (rectangle.contains(p))
g2d.setColor(Color.ORANGE);
} catch (NoninvertibleTransformException e) {
e.printStackTrace();
}

}

}
g2d.fill(rectangle);

}

};

frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
frame.setBounds(100, 100, 500, 300);
frame.setVisible(true);

}

}

: