2012-12-20 1 views
3

문제가 무엇이든 찾을 수없는 경우에도이 프로그램을 작동 시키려고했습니다. 이 프로그램은 다음과 같은 두 가지 수업으로 구성됩니다. 기본적으로 드로잉 영역의 각 클릭에 점을 그려야하며 3 번째 클릭시 모든 점이 연결됩니다. 나는 그것을 더 예쁘고 더 정확하게 만들기 위해 여전히 노력해야하지만이 부분은 효과적이다. 작동하지 않는 것은 다음과 같습니다. 네 번째 클릭에서 스레드가 시작되고 시작되고 삼각형 자체가 임의의 새로 고침 속도로 회전해야 정확히 80 회 다시 칠합니다. 애니메이션이 끝날 때까지 다음 클릭은 작동하지 않아야하며 애니메이션이 멈춘 후에 (스레드가 죽는) 클릭이 있으면 새 점이 표시되고 다시 시작됩니다.스레드가 실행 중일 때 회전 변환이 다시 그리기 작업에서 제대로 작동하지 않습니다.

모든 페인트 호출이 스레드 끝까지 쌓일 수 있습니까? 모든 이벤트가 이벤트 대기열에 쌓여 하나처럼 처리 될 수 있습니다. 시간 매개 변수로 다시 그리기를 사용하면 도움이되지 않습니다. 나는 모든 변수가 프랑스어 단어 (설명되어 있기 때문에)를 설명하기 위해 주석을 추가했습니다. 스레드 관련 또는 형식 관련 이건간에 문제를 찾기 위해 코드에 코드가 있는지 파악하려고 힘듭니다. 난 그냥 아무데도 디버그 모드 (Eclipse 사용) 갈거야. 나는 명백한 것을 완전히 무시 했습니까?

내 방법이이 작업을 수행하는 가장 효율적인 방법은 아니지만 로테이션이 주요 문제입니다. 코드의 작성되지 않은 나머지 부분을 처리 할 수 ​​있습니다. 도움 주셔서 감사합니다! 여기에 두 개의 클래스는 다음과 같습니다

import java.awt.EventQueue; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.border.EmptyBorder; 
import javax.swing.JButton; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 


public class Application extends JFrame { 

private static final long serialVersionUID = 1L; 
private JPanel contentPane; 
private JButton btnTerminer; 
private Triangle triangle; 
private int totalClics = 0; 

/** 
* Launch the application. 
*/ 
public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       Application frame = new Application(); 
       frame.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

/** 
* Create the frame. 
*/ 
public Application() { 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 453, 692); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    setContentPane(contentPane); 
    contentPane.setLayout(null); 

    btnTerminer = new JButton("Terminer"); 
    btnTerminer.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) { 
      System.exit(0); 
     } 
    }); 
    btnTerminer.setBounds(138, 622, 132, 23); 
    contentPane.add(btnTerminer); 

    triangle = new Triangle(); 
    //Adds points for every mouse click 
    triangle.addMouseListener(new MouseAdapter() { 
     @Override 
     public void mouseClicked(MouseEvent e) { 
      if(totalClics < 3){ 
       triangle.ajouterPoint(e.getX(), e.getY()); 
       totalClics++; 
      } else { 
       triangle.getAnim().start(); 
       totalClics = 0; 
      } 
     } 
    }); 
    triangle.setBounds(10, 11, 400, 600); 
    contentPane.add(triangle); 
} 
} 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.io.Serializable; 
import java.util.ArrayList; 
import java.util.Iterator; 


import javax.swing.JPanel; 


public class Triangle extends JPanel implements Runnable,Serializable{ 

private static final long serialVersionUID = 1L; 
private ArrayList<Point> points = null; 
//Animation thread 
private Thread anim; 
private Color couleurPrin; 
private Color couleurBoite; 
//A point's diameter 
private int diametre = 8; 
//The rectangle's width 
private int largeur; 
//The rectangle's height 
private int hauteur; 
//The rectangle's top-left corner 
private int minX; 
private int minY; 
//Angle incrementation multiplier 
private int nbAng = 0 ; 
//Thread stopping variable 
private boolean continuer = true; 


public Triangle() { 
    setPreferredSize(new Dimension(400, 600)); 
    setBackground(Color.BLACK); 
    couleurPrin = Color.GREEN; 
    couleurBoite = Color.RED; 
    setAnim(new Thread(this)); 
    points = new ArrayList<Point>(); 


} 
/** 
* Repaints this component 
*/ 
@Override 
public void paintComponent(Graphics g){ 
    super.paintComponent(g); 
    Graphics2D g2d = (Graphics2D) g; 
    int i = 0; 
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
    int[] coorX = new int[points.size()+1]; 
    int[] coorY = new int[points.size()+1]; 
    Iterator<Point> iter = points.iterator(); 
    while(iter.hasNext()){ 
     Point p = iter.next(); 
     coorX[i] = p.getX(); 
     coorY[i]= p.getY(); 
     i++; 
    } 
    coorX[points.size()] = coorX[0]; 
    coorY[points.size()] = coorY[0]; 
    if(points.size() != 0){ 
     g2d.setColor(Color.white); 
     g2d.fillOval(minX+largeur/2, minY+hauteur/2, 6, 6); 
     g2d.setColor(couleurPrin); 
     for(i =0; i<points.size(); i++){ 
      g2d.drawLine(coorX[i], coorY[i], coorX[i+1], coorY[i+1]); 
     } 
     for(i = 0; i<points.size(); i++){ 
      g2d.fillOval(coorX[i]-diametre/2, coorY[i]-diametre/2, diametre, diametre); 
     } 
     g2d.setColor(couleurBoite); 
     g2d.drawRect(minX, minY, largeur, hauteur); 
     g2d.rotate(15.0*nbAng, (largeur+getWidth())/2, (hauteur+getWidth())/2); 


    } 

} 
/** 
* Adds a point. Stops at 3. 
* @param x 
* @param y 
* 
* 
*/ 
public void ajouterPoint(int x, int y){ 
    Point p = new Point(x,y); 
    System.out.println(p.toString()); 
    if(points.size()>=0 && points.size()<3){ 
     points.add(p); 
     minX = p.getX()-3; 
     minY = p.getY()-3; 
    } 
    if(points.size() == 3){ 
     rectanguler(points); 
    } 
    repaint(); 

} 

public Color getCouleurPrin() { 
    return couleurPrin; 
} 
public void setCouleurPrin(Color c) { 
    this.couleurPrin = c; 
    repaint(); 
} 
public int getDiametre() { 
    return diametre; 
} 
public void setDiametre(int d) { 
    this.diametre = d; 
    repaint(); 
} 
/** 
* Sets rectangle's values to the largest bounds possible 
* @param points 
*/ 
private void rectanguler(ArrayList<Point> points){ 
    Iterator<Point> iter = points.iterator(); 
    Point p1, p2, p3; 
    p1 = iter.next(); 
    p2 = iter.next(); 
    p3 = iter.next(); 
    int dLarg; 
    int dLong; 
    if(p2 != null && p3 != null){ 
     minX = Math.min(p1.getX(), p2.getX()); 
     minY = Math.min(p1.getY(), p2.getY()); 
     largeur = Math.abs(p1.getX()-p2.getX()); 
     hauteur = Math.abs(p1.getY()-p2.getY()); 
     if(p3 != null){ 
      minX = Math.min(minX, p3.getX()); 
      minY = Math.min(minY, p3.getY()); 
      dLarg = Math.max(Math.abs(p3.getX()-p2.getX()), Math.abs(p3.getX()-p1.getX())); 
      dLong = Math.max(Math.abs(p3.getY()-p2.getY()), Math.abs(p3.getY()-p1.getY())); 
      largeur = Math.max(dLarg, largeur); 
      hauteur = Math.max(dLong, hauteur); 
     }  
    } 
} 
/** 
* Custom point class 
* Stores an x and y value 
* 
*/ 
private class Point{ 
    @Override 
    public String toString() { 
     return "Point [x=" + x + ", y=" + y + "]"; 
    } 
    private int x,y; 
    public Point(){ 
     setX(0); 
     setY(0); 
    } 
    public Point(int x,int y){ 
     setX(x); 
     setY(y); 
    } 
    public int getX() { 
     return x; 
    } 
    public void setX(int x) { 
     this.x = x; 
    } 
    public int getY() { 
     return y; 
    } 
    public void setY(int y) { 
     this.y = y; 
    } 

} 
/** 
* Starts the rotation 
* 
*/ 
@Override 
public void run() { 
    int i =1; 
    while(continuer){ 

     nbAng = i; 
     repaint(); 
     try { 
      Thread.sleep(200); 
     } catch (InterruptedException e) { 
      System.out.println("Erreur dans le thread"); 
      e.printStackTrace(); 
     } 
     i++; 
     if(i== 80){ 
      continuer = false; 
     } 
    } 
    anim = new Thread(this); 

} 
public Thread getAnim() { 
    return anim; 
} 
public void setAnim(Thread anim) { 
    this.anim = anim; 
    repaint(); 
} 

} 
+2

* "인 JPanel는 Runnable를 구현 연장)

나는 (죄송합니다, 당신이 그것을 제거 할 수 있어야 Triangle 클래스에 처리 마우스 클릭을 이동하지만) 약간의 예로서 코드를 수정 "* 위험 신호가 있습니다. Swing의'Timer'로부터'repaint()'를 방아쇠합니다. –

답변

3

첫 번째 문제는 당신이 애니메이션 스레드에서 start()를 호출하지 않을 것입니다.

두 번째 문제는 이 아니어야합니다.은 EDT 외부의 물건을 사용해야합니다. @AndrewThompson이 그의 코멘트에 언급 한 바와 같이 스레드 대신 스윙 Timer을 사용해야합니다.

+0

'repaint() '를 호출하는 것 이외에 EDT 밖에서 어떤 일을하는지 명확히하십시오. –

+0

쓰레드도 재진입하지 않습니다 ... – MadProgrammer

+0

@HovercraftFullOfEels - 그는 'repaint()'를 호출합니다. 이것은 gui 항목입니다. 당신이 명확히하기를 바라는 것이 확실하지 않은가요? – jtahlborn

3

Thread은 달성하려는 목표를 초과 달성 한 것입니다. javax.swing.Timer은 더 간단하고 사용하기 쉽고 Thread과 달리 재사용이 가능합니다.

Graphics2D#rotate은 이후의 모든 렌더링에 번역을 적용합니다. 즉, 페인트하기 전에 적용해야합니다.

마우스 클릭 논리는 약간 떨어져 있으며 클릭을 계속 허용하기 전에 스레드의 상태를 확인하지 않습니다.

public class TestRotation01 { 

    public static void main(String[] args) { 
     new TestRotation01(); 
    } 

    public TestRotation01() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new Triangle()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class Triangle extends JPanel { 

     private static final long serialVersionUID = 1L; 
     private ArrayList<Point> points = null; 
//Animation thread 
//  private Thread anim; 
     private Color couleurPrin; 
     private Color couleurBoite; 
//A point's diameter 
     private int diametre = 8; 
//The rectangle's width 
     private int largeur; 
//The rectangle's height 
     private int hauteur; 
//The rectangle's top-left corner 
     private int minX; 
     private int minY; 
//Angle incrementation multiplier 
     private int nbAng = 0; 
//Thread stopping variable 
     private boolean continuer = true; 
     private int totalClics = 0; 
     private Timer timer; 
     private int cycle; 

     public Triangle() { 
      setPreferredSize(new Dimension(400, 600)); 
      setBackground(Color.BLACK); 
      couleurPrin = Color.GREEN; 
      couleurBoite = Color.RED; 
      points = new ArrayList<Point>(); 
      addMouseListener(new MouseAdapter() { 
       @Override 
       public void mouseClicked(MouseEvent e) { 
        if (!timer.isRunning()) { 
         if (totalClics < 3) { 
          nbAng = 0; 
          ajouterPoint(e.getX(), e.getY()); 
          totalClics++; 
         } else { 
          cycle = 0; 
          totalClics = 0; 
          timer.restart(); 
         } 
        } 
       } 
      }); 

      timer = new Timer(200, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        nbAng += 5; 
        repaint(); 
        cycle++; 
        if (cycle == 80) { 
         timer.stop(); 
        } 
       } 
      }); 
      timer.setRepeats(true); 
      timer.setCoalesce(true); 
     } 

     /** 
     * Repaints this component 
     */ 
     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 

      if (timer.isRunning()) { 

       g2d.rotate(15.0 * nbAng, (largeur + getWidth())/2, (hauteur + getWidth())/2); 

      } 

      int i = 0; 
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      int[] coorX = new int[points.size() + 1]; 
      int[] coorY = new int[points.size() + 1]; 
      Iterator<Point> iter = points.iterator(); 
      while (iter.hasNext()) { 
       Point p = iter.next(); 
       coorX[i] = p.getX(); 
       coorY[i] = p.getY(); 
       i++; 
      } 
      coorX[points.size()] = coorX[0]; 
      coorY[points.size()] = coorY[0]; 
      if (points.size() != 0) { 
       g2d.setColor(Color.white); 
       g2d.fillOval(minX + largeur/2, minY + hauteur/2, 6, 6); 
       g2d.setColor(couleurPrin); 
       for (i = 0; i < points.size(); i++) { 
        g2d.drawLine(coorX[i], coorY[i], coorX[i + 1], coorY[i + 1]); 
       } 
       for (i = 0; i < points.size(); i++) { 
        g2d.fillOval(coorX[i] - diametre/2, coorY[i] - diametre/2, diametre, diametre); 
       } 
       g2d.setColor(couleurBoite); 
       g2d.drawRect(minX, minY, largeur, hauteur); 
      } 

      g2d.dispose(); 

     } 

     /** 
     * Adds a point. Stops at 3. 
     * 
     * @param x 
     * @param y 
     * 
     * 
     */ 
     public void ajouterPoint(int x, int y) { 
      Point p = new Point(x, y); 
      System.out.println(p.toString()); 
      if (points.size() >= 0 && points.size() < 3) { 
       points.add(p); 
       minX = p.getX() - 3; 
       minY = p.getY() - 3; 
      } 
      if (points.size() == 3) { 
       rectanguler(points); 
      } 
      repaint(); 

     } 

     public Color getCouleurPrin() { 
      return couleurPrin; 
     } 

     public void setCouleurPrin(Color c) { 
      this.couleurPrin = c; 
      repaint(); 
     } 

     public int getDiametre() { 
      return diametre; 
     } 

     public void setDiametre(int d) { 
      this.diametre = d; 
      repaint(); 
     } 

     /** 
     * Sets rectangle's values to the largest bounds possible 
     * 
     * @param points 
     */ 
     private void rectanguler(ArrayList<Point> points) { 
      Iterator<Point> iter = points.iterator(); 
      Point p1, p2, p3; 
      p1 = iter.next(); 
      p2 = iter.next(); 
      p3 = iter.next(); 
      int dLarg; 
      int dLong; 
      if (p2 != null && p3 != null) { 
       minX = Math.min(p1.getX(), p2.getX()); 
       minY = Math.min(p1.getY(), p2.getY()); 
       largeur = Math.abs(p1.getX() - p2.getX()); 
       hauteur = Math.abs(p1.getY() - p2.getY()); 
       if (p3 != null) { 
        minX = Math.min(minX, p3.getX()); 
        minY = Math.min(minY, p3.getY()); 
        dLarg = Math.max(Math.abs(p3.getX() - p2.getX()), Math.abs(p3.getX() - p1.getX())); 
        dLong = Math.max(Math.abs(p3.getY() - p2.getY()), Math.abs(p3.getY() - p1.getY())); 
        largeur = Math.max(dLarg, largeur); 
        hauteur = Math.max(dLong, hauteur); 
       } 
      } 
     } 

     /** 
     * Custom point class Stores an x and y value 
     * 
     */ 
     private class Point { 

      @Override 
      public String toString() { 
       return "Point [x=" + x + ", y=" + y + "]"; 
      } 
      private int x, y; 

      public Point() { 
       setX(0); 
       setY(0); 
      } 

      public Point(int x, int y) { 
       setX(x); 
       setY(y); 
      } 

      public int getX() { 
       return x; 
      } 

      public void setX(int x) { 
       this.x = x; 
      } 

      public int getY() { 
       return y; 
      } 

      public void setY(int y) { 
       this.y = y; 
      } 
     } 
    } 
} 
+0

고마워요! 두 답변 모두 문제의 원인을 파악하는 데 도움이되었습니다. 이 작은 프로그램은 스레드에 대한 연습 이었기 때문에 타이머가 방금 작업을 수행 할 수있는 스레드가 눈에 띄게 사용되었습니다. – gabarise

관련 문제