2014-09-29 187 views
0

因此,我有一个程序,可以使用Path2D对象向JPanel添加形状,然后单击并拖动它们。我想要做的是能够找到药物后形状的最终X和Y坐标。坐标需要为左上坐标。有任何想法吗?为抵消获取在Jpanel上绘制的Path2D形状的(起始)X和Y坐标

// add a circle to center of the screen 
public void addCircle(int width, int height) { 
    Path2D circ = new Path2D.Double(); 
    circ.append(new Ellipse2D.Double(getWidth()/2 - width/2, 
      getHeight()/2 - height/2, width, height), true); 
    shapes.add(circ); 
    repaint(); 
} 
      .................. 
//paint all shapes 
@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    this.setOpaque(true); 
    this.setBackground(Color.WHITE); 
    Graphics2D g2 = (Graphics2D) g; 
    g2.setStroke(new BasicStroke(2)); 
    for (Path2D shape : shapes) { 
     g2.draw(shape); 
    } 
} 
      .................. 
    // if the mouse click is in the circle, set pressed=true 
    @Override 
    public void mousePressed(MouseEvent e) { 
     if (e.getButton() != MouseEvent.BUTTON1) { 
      return; 
     } 
     for (int i = 0; i < shapes.size(); i++) { 
      if (shapes.get(i) != null 
        && shapes.get(i).contains(e.getPoint())) { 
       currentIndex = i; 
       pressed = true; 
       this.point = e.getPoint(); 
      } 
     } 
    } 

    //if pressed=true, move circle with mouse 
    @Override 
    public void mouseDragged(MouseEvent e) { 
     if (pressed && !lineSelected) { 
      int deltaX = e.getX() - point.x; 
      int deltaY = e.getY() - point.y; 
      shapes.get(currentIndex).transform(
        AffineTransform.getTranslateInstance(deltaX, deltaY)); 
      point = e.getPoint(); 
      //I need to find the new coordinates here!!!!!!!!!!! 
      repaint(); 
     } 
    } 

全码

class Canvas extends JPanel { 
private static final long serialVersionUID = 1L; 

private List<Path2D> shapes = new ArrayList<Path2D>(); 
private int currentIndex; 
private Point lineStartingPoint = new Point(); 
private Point lineEndingPoint = new Point(); 
private boolean drawing; 
private boolean lineSelected; 
private Path2D.Double linePath; 
private Shapes myShapes = new Shapes(); 
private List<Path2D> circles = new ArrayList<Path2D>(); 

public Canvas() { 
    MyMouseAdapter myMouseAdapter = new MyMouseAdapter(); 
    addMouseListener(myMouseAdapter); 
    addMouseMotionListener(myMouseAdapter); 
} 

public void setList(ArrayList<UMLCircle> shapes) { 

} 

public List<UMLCircle> getList() { 
    return null; 
} 

public void addSquare(int width, int height) { 
    Path2D rect2 = new Path2D.Double(); 
    rect2.append(new Rectangle(getWidth()/2 - width/2, getHeight()/2 
      - height/2, width, height), true); 

    shapes.add(rect2); 
    repaint(); 
} 

public void addLine() { 
    lineSelected = true; 
    repaint(); 
} 

public void addCircle(int width, int height) { 
    myShapes.addCircle(getWidth()/2 - width/2, getHeight()/2 - height 
      /2, width, height); 
    Path2D circ = new Path2D.Double(); 
    circ.append(new Ellipse2D.Double(getWidth()/2 - width/2, 
      getHeight()/2 - height/2, width, height), true); 
    circles.add(circ); 
    shapes.add(circ); 
    repaint(); 
} 

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    this.setOpaque(true); 
    this.setBackground(Color.WHITE); 
    Graphics2D g2 = (Graphics2D) g; 
    if (lineSelected) { 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
       RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setStroke(new BasicStroke(2)); 
     g2.drawLine(lineStartingPoint.x, lineStartingPoint.y, 
       lineEndingPoint.x, lineEndingPoint.y); 
    } 
    g2.setStroke(new BasicStroke(2)); 
    for (Path2D shape : shapes) { 
     g2.draw(shape); 
    } 
} 

class MyMouseAdapter extends MouseAdapter { 
    private boolean pressed = false; 
    private Point point; 

    @Override 
    public void mousePressed(MouseEvent e) { 
     if (e.getButton() != MouseEvent.BUTTON1) { 
      return; 
     } 
     for (int i = 0; i < shapes.size(); i++) { 
      if (shapes.get(i) != null 
        && shapes.get(i).contains(e.getPoint())) { 
       currentIndex = i; 
       pressed = true; 
       this.point = e.getPoint(); 
      } 
      if (circles.get(i) != null 
        && circles.get(i).contains(e.getPoint())) { 
       currentIndex = i; 
       pressed = true; 
       this.point = e.getPoint(); 
      } 
     } 
     if (lineSelected) { 
      drawing = true; 
      lineStartingPoint = e.getPoint(); 
      lineEndingPoint = lineStartingPoint; 
     } 
    } 

    @Override 
    public void mouseDragged(MouseEvent e) { 
     if (pressed && !lineSelected) { 
      int deltaX = e.getX() - point.x; 
      int deltaY = e.getY() - point.y; 
      shapes.get(currentIndex).transform(
        AffineTransform.getTranslateInstance(deltaX, deltaY)); 
      point = e.getPoint(); 
      myShapes.updateCircleLocation(currentIndex, point.x, point.y); 
      System.out.println(point.x + " " + point.y); 
      repaint(); 
     } 
     if (drawing) { 
      lineEndingPoint = e.getPoint(); 
      repaint(); 
     } 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 
     if (drawing && lineSelected) { 
      drawing = false; 
      lineSelected = false; 
      lineEndingPoint = e.getPoint(); 
      linePath = new Path2D.Double(); 
      linePath.moveTo(lineStartingPoint.getX(), 
        lineStartingPoint.getY()); 
      linePath.lineTo(lineEndingPoint.getX(), lineEndingPoint.getY()); 
      shapes.add(linePath); 
      repaint(); 
     } 
     pressed = false; 
    } 
} 
} 

编辑

计算:

  int deltaX = e.getX() - point.x; 
      int deltaY = e.getY() - point.y; 
      shapes.get(currentIndex).transform(
        AffineTransform.getTranslateInstance(deltaX, deltaY)); 
      point = e.getPoint(); 
      int newXPos = e.getX() - deltaX; // final X pos 
      int newXPos = e.getX() - deltaX; // final Y pos 
+0

您需要o计算形状的x/y位置处的按压点之间的差异,这将成为偏移量。当拖动形状时,您将从鼠标点中减去偏移量,每个wod都会给出形状应该出现的x/y位置... – MadProgrammer 2014-09-29 21:00:41

+0

鉴于您将添加不同类型的形状,因此作为一个标准没有简单的答案计算积分的方法不适用于所有人。比如计算一个正方形的左上角,这很简单,根本不适用于一个圆。也许有一个问题,你可以得到一个答案,你可以从预期的最终结果中得出答案。 – MarGar 2014-09-29 21:21:45

+0

@MadProgrammer我已经编辑过来添加我的计算,但是当我用给定的X,Y坐标绘制圆时,它稍微偏离了一点(这个圆稍微向原始的左下方绘制)。我究竟做错了什么? – Harry 2014-09-29 22:55:03

回答

3

之前,你可以做任何事情,你需要知道的偏移从t点击鼠标他形状的角落,这将让你因此它不会突然“跳”到你当前鼠标的位置拖动对象...

@Override 
public void mousePressed(MouseEvent e) { 
    //... 
    for (Shape shape : myShapes) { 
      //... 
      this.point = e.getPoint(); 
      int deltaX = point.x - shape.getBounds().x; 
      int deltaY = point.y - shape.getBounds().y; 
      offset = new Point(deltaX, deltaY); 
      //... 
     } 
    } 
} 

然后,您会计算变化的三角洲,之间当前鼠标位置和偏移量。因为你申请一个翻译,你还需要减去形状的当前位置,因为翻译是基于形状的当前位置,我们只想要应用的变化量

@Override 
public void mouseDragged(MouseEvent e) { 
    if (pressed) { 
     int index = myShapes.indexOf(clickedShape); 
     myShapes.remove(index); 

     int deltaX = e.getPoint().x - offset.x; 
     int deltaY = e.getPoint().y - offset.y; 

     clickedShape = new Path2D.Double(clickedShape, 
         AffineTransform.getTranslateInstance(
             deltaX - clickedShape.getBounds().x, 
             deltaY - clickedShape.getBounds().y)); 
     myShapes.add(index, clickedShape); 
     point = e.getPoint(); 
     repaint(); 
    } 
} 

现在,所有说即,不这样做......

protected void paintComponent(Graphics g) { 
    //... 
    this.setOpaque(true); 
    this.setBackground(Color.WHITE); 

从paint方法中改变组件的状态可以设置重绘请求,可以塞满您的系统的无限循环。此外,你做不会应用到当前图形上下文,因为这些属性通常由paint方法应用的更改...

和工作副本....

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Path2D; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

class Canvas extends JPanel { 

    private static final long serialVersionUID = 1L; 

    private boolean drawing; 
    private List<Shape> myShapes = new ArrayList<Shape>(); 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new Canvas()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public Canvas() { 
     MyMouseAdapter myMouseAdapter = new MyMouseAdapter(); 
     addMouseListener(myMouseAdapter); 
     addMouseMotionListener(myMouseAdapter); 
     addSquare(100, 100); 
    } 

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

    public void setList(ArrayList<Shape> shapes) { 

    } 

    public List<Shape> getList() { 
     return null; 
    } 

    public void addSquare(int width, int height) { 
     Path2D rect2 = new Path2D.Double(); 
     rect2.append(new Rectangle(getWidth()/2 - width/2, getHeight()/2 
         - height/2, width, height), true); 

     myShapes.add(rect2); 
     repaint(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setStroke(new BasicStroke(2)); 
     for (Shape shape : myShapes) { 
      g2.draw(shape); 
     } 
    } 

    class MyMouseAdapter extends MouseAdapter { 

     private boolean pressed = false; 
     private Point point; 
     private Point offset; 
     private Shape clickedShape; 

     @Override 
     public void mousePressed(MouseEvent e) { 
      if (e.getButton() != MouseEvent.BUTTON1) { 
       return; 
      } 
      for (Shape shape : myShapes) { 
       if (shape != null 
           && shape.contains(e.getPoint())) { 
        System.out.println("Clicked"); 
        pressed = true; 
        clickedShape = shape; 
        this.point = e.getPoint(); 
        int deltaX = point.x - shape.getBounds().x; 
        int deltaY = point.y - shape.getBounds().y; 
        offset = new Point(deltaX, deltaY); 
        System.out.println(point + "x" + offset); 
        repaint(); 
        break; 
       } 
      } 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
      if (pressed) { 
       int index = myShapes.indexOf(clickedShape); 
       myShapes.remove(index); 

       int deltaX = e.getPoint().x - offset.x; 
       int deltaY = e.getPoint().y - offset.y; 

       clickedShape = new Path2D.Double(clickedShape, 
           AffineTransform.getTranslateInstance(
               deltaX - clickedShape.getBounds().x, 
               deltaY - clickedShape.getBounds().y)); 
       myShapes.add(index, clickedShape); 
       point = e.getPoint(); 
       repaint(); 
      } 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      offset = null; 
      pressed = false; 
     } 
    } 
} 
+0

我得到了这个工作,但你能解释我在哪里可以调用'this.setOpaque(true); this.setBackground(Color.WHITE);'?如果我完全删除它,背景仍然是灰色的。再次感谢 – Harry 2014-10-01 01:19:40

+1

除了在绘画方法的范围内,您可以在任何地方调用它。它似乎工作的原因是组件第一次被绘制,你改变背景颜色,这会导致另一个重绘和另一个重绘,另一个重绘和另一个重绘,另一个重绘和另一个重绘...所以调用这些方法在构造函数,他们所属... – MadProgrammer 2014-10-01 02:01:25

+0

这是有道理的啊。知道了谢谢。 – Harry 2014-10-01 02:21:23