2009-12-10 4 views
0

원을 화면에 표시하려고 할 때 사용자가 원 안쪽을 클릭하면 마우스가 눌러지는 동안 원이 드래그되는 기능이 활성화됩니다.JFrame의 원을 끌기

이것은 내가 지금까지 가지고있는 코드입니다. 드래그가 작동하지만, 화면의 아무 곳이나 누르면 서클 내부를 누르지 않고 드래그 할 수 있습니다. 내가

여기 내가 가지고있는 코드가 너무 복잡하지 않다 희망

는, 사람이 바로 나에게 수정해야하는 코드를 말할 수하십시오, 그것은 더 이상 시간을 저를 저장합니다.

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

public class DragCircle extends JFrame { 
    private static final long serialVersionUID = 1L; 

    public static int size = 400; 

    public static int r = 10; 

    private int x; 

    private int y; 

    private int cX; 

    private int cY; 

    private int dX; 

    private int dY; 

    private MouseHandler mh; 

    boolean isCircleClicked = false; 

    public static void main(String[] args) { 
     DragCircle c1 = new DragCircle(); 
     c1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    } 

    public DragCircle() { 

     super("Drag circle"); 

     cX = r + 100; 
     cY = r + 100; 

     mh = new MouseHandler(); 
     addMouseListener(mh); 
     addMouseMotionListener(mh); 

     setSize(size, size); 
     setVisible(true); 

    } 

    public void paint(Graphics g) { 
     super.paint(g); 
     g.setColor(Color.RED); 
     g.fillOval(cX, cY, r * 2, r * 2); 

    } 

    private class MouseHandler extends MouseAdapter implements 
      MouseMotionListener { 
     public void mousePressed(MouseEvent me) 

     { 

      if ((cX - me.getX()) * (cX - me.getX()) + (cY - me.getY()) 
        * (cY - me.getY()) < r * r) { 
       isCircleClicked = true; 
      } 
     } 

     public void mouseDragged(MouseEvent me) { 
      if (isCircleClicked) { 

       x = me.getX() - dX; 
       y = me.getY() - dY; 
       cX = x + r; 
       cY = y + r; 
       repaint(); 
      } 
     } 

     public void mouseReleased(MouseEvent e) { 
      isCircleClicked = false; 
     } 

    } 

} 
+0

당신은 mouseReleased에 대해 옳았습니다. 나는 그것을 넣을 것이고, 이렇게 컴파일했습니다. – Madison

답변

0

프로그램 구조가 잘못되었습니다. JFrame의 paint (...) 메소드를 오버라이드해서는 안됩니다. 그것은 오래된 AWT 트릭이므로 Swing과 함께 사용하면 안됩니다.

그림을 그리는 적절한 방법의 예는 Custom Painting에있는 스윙 튜토리얼의 섹션을 읽으십시오. 기본 사항은 JPanel의 paintComponent (...) 메서드를 재정의 한 다음이 패널을 프레임의 내용 창에 추가하는 것입니다.

더 나은 해결책은 원을 나타내는 Elllipse2D 객체를 만드는 것입니다. 다음에, 커스텀 페인팅은 Graphics2D 클래스의 drawShape (...) 메소드를 사용할 수있다. 그런 다음 MouseListener 코드에서 Shape.contains (...) 메서드를 사용하여 원을 마우스로 클릭했는지 확인할 수 있습니다.

+0

원을 치고 테스트하는 것은 간단하지만 히트 테스트 코드는 나에게 맞습니다. OP가 먼저 동그라미를 움직이고 그 다음에 * then *이 바깥쪽으로 끌려고 할 때만 발생한다고 가정합니다 ('isCircleClicked'는 여전히'true '로 설정되어 원을 움직입니다). – Joey

+0

코드를 고려하여 적절한 좌표를 고려해야합니다. 그 이유는 Shape 객체를 사용하는 것이 더 쉽기 때문에 세부 사항을 염려 할 필요가없고 contains (...) 메소드를 호출하기 때문입니다. API가 아니라 바퀴를 재발견하는 것입니다. – camickr

2

귀하의 한 가지 문제가

public void mouseDragged(MouseEvent me) { 
    if (isCircleClicked = true) { 

는 당신이 여기에서하고있는 것은 true에 마우스를 드래그 할 때마다 isCircleClicked을 설정하는 것입니다 함께. 또한이 진술은 true으로 평가되므로 어디든 드래그하여 서클을 움직일 수 있습니다. 이 번호를

if (isCircleClicked) { 

으로 변경하면 여기에 문제가 없습니다.

다음 문제는 isCircleClickedfalse으로 다시 설정하지 않는다는 것입니다. 당신도 mouseReleased에서이 일을 또는 다음과 같이 mousePressed을 변경해야합니다

public void mousePressed(MouseEvent me) { 
    isCircleClicked = 
     (cX - me.getX()) * (cX - me.getX()) + 
     (cY - me.getY)) * (cY - me.getY()) < r * r; 
} 

따라 isCircleClicked을 설정할 것이다.

그래도 할 일이 있습니다. 이 때문에 도면이다

 
+------+ 
|  | 
| .-|-. 
| /| \ 
+------+ | 
    \ /
    '-_-' 

: fillOval는 타원형 폭의 왼쪽 코너킥을 얻어냅니다 아래 그림과 같이 현재의 형태에서는, 중심점의 왼쪽으로 드래그 시작해야 경계 사각형의 높이. 이 아니고 중심점과 해당 지름입니다. 따라서 다음과 같이 자신을 적응해야

g.fillOval(cX - r, cY - r, r * 2, r * 2); 

참고는 왼쪽 상단에 위치 반경에 의해 상쇄.

또한 드래그 코드는 좀 더 많은 작업이 필요합니다.현재 사용자가 서클의 센터을 드래그한다고 가정합니다. 당신이해야 할 일은 마우스 클릭의 좌표를 저장하고 마우스의 움직임에 따라 원을 움직입니다. 현재 원의 중심을 기준으로 이동하므로 원의 중심에서 정확하게 드래그를 시작해야 운동이 원활 해집니다.

게다가 수신기 클래스는 이미 MouseAdapter에서 상속되므로 MouseAdapter가 이미 구현 했으므로 MouseMotionListener를 명시 적으로 구현할 필요가 없습니다.

+0

난 그냥 코드를 업데이 트 .. 내가 뭘했는지 보여주기 위해 게시물을 편집했지만 그 이상한 행동, 내가 원을 돌릴 때 전혀 움직이지 않을거야 – Madison

+0

조금 드래그 해보세요. 그 원의 왼쪽과 맨 위에 놓습니다. 그것은 나를 위해 작동합니다. 왜 이제는 원을 올바르게 테스트했는지 알아 내야 만합니다 ... – Joey

+0

문제를 발견했습니다. – Joey