2012-12-20 73 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 「*有危險的跡象。從Swing Timer中觸發'repaint()'。 –

回答

3

第一個問題是,你永遠不會調用start()動畫線程上。

第二個問題是,你應該從來沒有做gui東西以外的EDT。正如@AndrewThompson在他的評論中提到的,你應該使用揮杆Timer而不是線程。

+0

請澄清 - 除了調用repaint()'之外,他在EDT之外做的是什麼GUI? –

+0

線程也沒有重入... – MadProgrammer

+0

@HovercraftFullOfEels - 他叫'repaint()',這是gui的東西。不確定你想讓我澄清什麼? – jtahlborn

3

A Thread對於您想實現的目標而言是矯枉過正的。 A javax.swing.Timer更簡單易用,與Thread不同,它也可重複使用。

Graphics2D#rotate將翻譯應用於所有後續渲染,這意味着您需要在繪製任何東西之前應用它。

您的鼠標點擊邏輯也有點偏離,它不會在允許點擊繼續之前檢查線程的狀態。

我修改您的代碼爲例一點(對不起,我移動鼠標點擊操作的Triangle類,但你應該能夠將其刪除;))

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