【Java】図形を拡大縮小/平行移動して表示する方法
CADソフトを作るために、マウス操作で作図した図形を拡大縮小、平行移動する方法を考えました。
AffineTransformを使う方法
ネットで検索すると出てくるのが、AffineTransformを使う方法です。これが一般的だと思います...
ところが!実際に表示してみると、下のようになってしまいます。
線の太さや、ゴツゴツ感まで拡大されてしまいます。
これは嫌なので、座標変換する方法を考えました。
AffineTransformは表示するパネルの方を拡大縮小/平行移動する方法です。
表示する点の座標を変換して、パネル側に手を加えなければ、下のように拡大しても線の太さは変わりません。
下のメソッドを作りました。
kS()は表示する図形をパネル上の座標に変換するもの、sK()はその逆で、マウスカーソル下の座標を計算するときなどに使います。
sx,syは平行移動の値、ssx,ssyは直近の新たな平行移動値。
scaleは画面のスケール。Px,pyは業がパネルの中心座標。
これで拡大縮小と平行移動ができるようになります。Px,pyをパネルの中心にしているので、拡大縮小がパネルの中心を中心にしてなされます。
Point kS( Point p)
{
Point rp = new Point();
rp.x = (int)((p.x + sx)*scale+px+ssx);
rp.y= (int)((-p.y + sy)*scale+py+ssy);
return rp;
}
Point sK( Point p)
{
Point rp = new Point();
rp.x = (int)((p.x - ssx - px ) / scale - sx);
rp.y= -(int)((p.y - ssy - py ) / scale - sy);
return rp;
}
拡大縮小動画
画像だけではわかりにくいので動画もUPしておきます。
ソースコード
動画のソースコードは下記です。
package tomojavalib.test;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.Jframe;
import javax.swing.Jpanel;
public class MouseCursor2 extends Jframe{
int bai=0;
//int cx=1;
//int cy=1;
double scale = 1. ;
double x=0.;
double y=0.;
int tmpsx=0;
int tmpsy=0;
double sx=0.;
double sy=0.;
double ssx=0.;
double ssy=0.;
Jpanel p = null;
double px=0.;
double py=0.;
int x1=-0;int y1=-0;
//int x2=25;int y2=25;
//拡大縮小
java.awt.geom.AffineTransform af = new java.awt.geom.AffineTransform();
public void paint(Graphics g){
System.out.println("再描画");
Graphics2D g2 = (Graphics2D)p.getGraphics();
//スケールの変更
if(bai==-1){scale=scale *.8;}else if(bai==1){scale=scale /.8;}
//パネルの中心
double px= (double)p.getWidth()/2.;double py= (double)p.getHeight()/2.;
//パネル側を拡大縮小する場合
// af.setToTranslation(sx*scale+px+ssx, sy*scale+py+ssy);
// af.scale(scale, scale);
// g2.setTransform(af);
//座標を変換する場合
x1= (int)((x + sx)*scale+px+ssx);
y1= (int)((y + sy)*scale+py+ssy);
System.out.println(x1+" "+scale);
//後処理
sx=sx+ssx/scale;sy=sy+ssy/scale;
ssx=0.;ssy=0.;
//四角形の描画
int haba=(int)(25*scale);
g2.drawRect(x1-haba, y1-haba, haba, haba);
g2.drawOval(x1-haba, y1-haba, haba, haba);
// sscale =scale;
// System.out.println(x1 +" "+ x2 +" "+ y1 +" "+ y2 +" "+ bai +" "+ scale);
bai=0;
}
public MouseCursor2()
{
p = new Jpanel();
p.setBackground(Color.red);
Container contentPane = getContentPane();
contentPane.add( p, BorderLayout.CENTER );
setByougapanel(p);
}
public static void main(String[] args) {
MouseCursor2 m = new MouseCursor2();
m.setSize(640,480);
m.setBackground(Color.WHITE);
m.setVisible(true);
}
public void setByougapanel( Jpanel p )
{
//マウスイベントを発生させる。
p.addMouseListener(
new MouseAdapter(){
//マウスクリック時のイベント
public void mouseClicked(MouseEvent e){
int mouseNo = e.getButton();
if( mouseNo==1 ){ System.out.println("マウス左ボタンがクリックされました"); }
else if( mouseNo==2 ){ System.out.println("マウス中ボタン楽天 がクリックされました"); }
else if( mouseNo==3 ){ System.out.println("マウス右ボタンがクリックされました"); }
}
public void mousePressed(MouseEvent e){
int mouseNo = e.getButton();
if( mouseNo==1 ){ System.out.println("マウス左ボタンが押されました"); }
else if( mouseNo==2 ){ tmpsx=e.getX();tmpsy=e.getY(); System.out.println("マウス中ボタンが押されました"); }
else if( mouseNo==3 ){ System.out.println("マウス右ボタンが押されました"); }
}
public void mouseReleased(MouseEvent e){
int mouseNo = e.getButton();
if( mouseNo==1 ){ System.out.println("マウス左ボタンが放されました"); }
else if( mouseNo==2 ){
System.out.println("マウス中ボタンが放されました");
ssx = e.getX() - tmpsx ;ssy = e.getY() -tmpsy;
e.consume();repaint();
}
else if( mouseNo==3 ){System.out.println("マウス右ボタンが放されました"); }
}
}
);
//マウスがパネル上を動いたらイベントを発生させる。
p.addMouseMotionListener(
new MouseMotionAdapter(){
//マウスが動いたときの処理
public void mouseMoved(MouseEvent e){
}
//マウスがドラッグされた時のイベント
public void mouseDragged(MouseEvent e){
//System.out.println( "マウスがドラッグ" );
}
}
);
//マウスホイールが動かされた場合のイベント
p.addMouseWheelListener(
new MouseWheelListener(){
public void mouseWheelMoved(MouseWheelEvent e) {
// cad.mx = e.getX();cad.my = e.getY();
bai = e.getWheelRotation() ;
System.out.println(e.getWheelRotation());
e.consume();
repaint();
}
}
);
}
}
最終更新日: 2018-12-21 08:45:48