2

私のプログラムでは、クリックした場所に三角形を描画します。

EcadクラスとLineクラスの2つのクラスがあります。Ecadはメインフレームであり、Lineクラスは線を描画するためのものです。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Ecad extends JFrame implements MouseListener{
    ArrayList<Line2> lines=new ArrayList();
    public Ecad(){
        this.setVisible(true);
        this.setSize(600,400);
        this.addMouseListener(this);
    }
    public void mouseReleased(MouseEvent me){
        Point p1,p2,p3;
        int X=me.getX();
        int Y=me.getY();
        p1=new Point(X,Y);                                                       
        p2=new Point((int)(p1.getX()-100),(int)(p1.getY()+(1.732/2*200)));
        p3=new Point((int)(p1.getX()+100),(int)(p1.getY()+(1.732/2*200)));                                          
        Line2 l1=new Line2(p2,p1);
        Line2 l2=new Line2(p1,p3);
        Line2 l3=new Line2(p2,p3);
        lines.add(l1);
        lines.add(l2);
        lines.add(l3);
        this.repaint();
    }
     public void mouseClicked(MouseEvent me){

    }
    public void mouseExited(MouseEvent me){

    }
    public void mouseEntered(MouseEvent me){

    }
    public void mousePressed(MouseEvent me){
    }
    public void mouseMoved(MouseEvent me){

    }
    public static void main(String args[]){
        new Ecad();
    }
    public void paint(Graphics g){
        Graphics2D g2=(Graphics2D)g;
        super.paintComponents(g2);
        //g2.scale(0.5, 0.5);
        for(final Line2 r:lines){
            r.paint((Graphics2D)g2);
        }
    }
}

これはLineクラスです

import java.awt.*;
public class Line2 {
    Point start,end;
    public Line2(Point a,Point b){    
        start=a;
        end=b;   
    }
    public void paint(Graphics2D g){
        g.drawLine((int)start.getX(),(int)start.getY(),(int)end.getX(),(int)end.getY());
    }

}

Ecadクラスのpaint()メソッドで、scaleオプションを使用してズームインまたはズームアウトすると、マウスの座標が変換されません。したがって、ズームした後、あるポイントをクリックすると、三角形は別のポイントに配置されます。グラフィックコンポーネントをスケーリングするときに、マウスの座標も変換する方法はありますか?

4

1 に答える 1

2

繰り返しますが、スケールと固定点を使用して、描画している形状を変換する必要があります (ここでも、各形状の固定点は三角形の頂点になるように見えますが、決定した場合は中心になる可能性があります。平行移動は単純な幾何学的原理に基づいており、fixedPoint.x * (1 - scale) / scale となり、y 平行移動についても同じです。

例(これは上記の例のようにJPanelを使用しています):

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.List;

class EcadB extends JPanel {
   private static final int PREF_W = 800;
   private static final int PREF_H = 600;
   private List<MyShape> myShapes = new ArrayList<MyShape>();
   private double scale = 1.0;
   private JSlider slider = new JSlider(0, 200, 100);

   public EcadB() {
      addMouseListener(new MyMouseAdapter());
      setLayout(new BorderLayout());

      slider.setOpaque(false);
      slider.setMajorTickSpacing(20);
      slider.setMinorTickSpacing(10);
      slider.setPaintLabels(true);
      slider.setPaintTicks(true);
      slider.addChangeListener(new SliderChangeListener());
      add(slider, BorderLayout.SOUTH);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      Graphics2D g2b = (Graphics2D)g2.create();
      g2b.scale(scale, scale);
      for (MyShape myShape : myShapes) {
         myShape.draw(g2b, scale);
      }
      g2b.dispose();
   }

   public void setScale(double scale) {
      this.scale = scale;
      repaint();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private class MyMouseAdapter extends MouseAdapter {
      @Override
      public void mousePressed(MouseEvent e) {
         Point2D p1 = e.getPoint();
         Point2D p2 = new Point((int) (p1.getX() - 100),
               (int) (p1.getY() + (1.732 / 2 * 200)));
         Point2D p3 = new Point((int) (p1.getX() + 100),
               (int) (p1.getY() + (1.732 / 2 * 200)));
         Path2D path = new Path2D.Double();
         path.moveTo(p1.getX(), p1.getY());
         path.lineTo(p2.getX(), p2.getY());
         path.lineTo(p3.getX(), p3.getY());
         path.lineTo(p1.getX(), p1.getY());

         myShapes.add(new MyShape(path, p1));
         repaint();
      }
   }

   private class SliderChangeListener implements ChangeListener {
      @Override
      public void stateChanged(ChangeEvent arg0) {
         double value = slider.getValue() / 100.0;
         setScale(value);
      }
   }

   public static void main(String args[]) {
      // new Ecad();
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            EcadB ecadB = new EcadB();
            JFrame frame = new JFrame("Scale");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(ecadB);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
         }
      });
   }
}

class MyShape {
   Shape shape;
   Point2D fixedPoint;

   public MyShape(Shape shape, Point2D fixedPoint) {
      this.shape = shape;
      this.fixedPoint = fixedPoint;
   }

   public void draw(Graphics2D g2, double scale) {
      Graphics2D g2b = (Graphics2D) g2.create();
      double tx = fixedPoint.getX() * (1.0 - scale) / scale;
      double ty = fixedPoint.getY() * (1.0 - scale) / scale;
      g2b.translate(tx, ty);
      g2b.draw(shape);
      g2b.dispose();
   }
}

Graphics オブジェクトによって描画される可能性のある他のオブジェクトに変換効果がないように、変換する前に Graphics オブジェクトのコピーを作成することに注意してください。たとえば、JPanel のpaintComponent(...)メソッドで使用している Graphics2D のコピーを削除すると、JSlider が他のすべてのものと一緒にスケーリングされることがわかります。

于 2012-04-10T21:51:01.000 に答える