2012-03-21 65 views
4

問題是當我調整JFrame的大小時,動畫會繼續使用Pre的尺寸JComponent。有沒有辦法可以在我調整JFrame的大小時更新我的​​widthheight變量,以便動畫可以與新的座標一起運行。Swing中的球動畫

簡單來說,說JComponent具有初始width = 300height = 300,所以這裏面的BALL移動指定Co-ordinates。現在,如果我調整JFrame的大小,則JComponent的大小仍然保持原樣,即width = 300height = 300,但我期望的是使用當前窗口大小修改這些變量的方法。如果我沒有解釋我的問題,請告訴我。

這裏是我使用的代碼:我希望你只需要綁定一些品種監聽器(?WindowEventListener)的

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

public class BallAnimation 
{ 
    private int x; 
    private int y; 
    private int count; 
    private int width; 
    private int height; 
    private int speedValue; 
    private boolean flag; 
    /* 
    * These variables are used to keep track of 
    * the ball, either it is going LEFT or RIGHT 
    * depending on that, we will set the 
    * Co-ordinates. 
    */ 
    private boolean toLeft, toRight; 

    private boolean fromTop, fromBottom; 

    private Timer timer; 

    private JButton button; 

    private ActionListener actionTimer; 
    private ActionListener buttonAction; 

    public BallAnimation() 
    { 
     x = y = count = 0; 
     flag = toLeft = false; 
     toRight = true; 
     fromTop = true; 
     fromBottom = false; 
     speedValue = 5; 
    } 

    public static void main(String args[]) 
    { 
     Runnable runnable = new Runnable() 
     { 
      public void run() 
      { 
       BallAnimation animation = new BallAnimation(); 
       animation.go(); 
      } 
     };  
     SwingUtilities.invokeLater(runnable); 
    } 

    public void go() 
    { 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     //JPanel contentPane = new JPanel(); 

     /* 
     * Class Name : 
     * Java Naming Convention says that class names 
     * should be in Pascal Case, i.e. the first 
     * letter of the class name should be capitalized 
     * and every new word must start with a capitalized 
     * Alphabet. 
     * For Example : 
     * public class ClassName{...} 
     * ---------------------------------------------------------- 
     * Variable Name : 
     * Java Naming Convention says that the variable name 
     * should be in Camel Case, i.e. the first letter of 
     * the variable name should be small case or _ (underscore) 
     * and every new word must start with a capitalized 
     * Alphabet. 
     * --------------------------------------------------------- 
     */ 
     final MyDraw drawPanel = new MyDraw(0, 0); 
     x = drawPanel.getXValue(); 
     y = drawPanel.getYValue(); 
     //contentPane.add(drawPanel); 

     actionTimer = new ActionListener() 
     { 
      public void actionPerformed(ActionEvent ae) 
      {    
       if (fromTop && !fromBottom && x < width && y < height 
          && toRight && !toLeft) 
       { 
        x += speedValue; 
        y += speedValue; 
       } 
       else if (fromTop && !fromBottom && x < width && y >= height 
           && toRight && !toLeft) 
       { 
        /* 
        * Since the ball coming from the TOP LEFT Side 
        * touched the BOTTOM of the JPanel. 
        */ 
        y -= speedValue; 
        x += speedValue; 
        fromTop = false; 
        fromBottom = true; 
       } 
       else if (!fromTop && fromBottom && x < width && y <= 0 
            && toRight && !toLeft) 
       { 
        /* 
        * Since the ball coming from BOTTOM LEFT Side 
        * touched the TOP of the JPanel. 
        */ 
        fromTop = true; 
        fromBottom = false; 
        x += speedValue; 
        y += speedValue; 
       } 
       else if (!fromTop && fromBottom && x < width && y < height 
            && toRight && !toLeft) 
       { 
        x += speedValue; 
        y -= speedValue; 
       } 
       else if (!fromTop && fromBottom && x >= width && y < height 
            && toRight && !toLeft) 
       { 
        /* 
        * Since the ball coming from the BOTTOM LEFT Side 
        * touched the RIGHT Side of the JPanel. 
        */ 
        toRight = false; 
        toLeft = true; 
        x -= speedValue; 
        y -= speedValue; 
       }     
       else if (!fromTop && fromBottom && x < width && y <= 0 
            && !toRight && toLeft) 
       { 
        /* 
        * Since the ball coming from the BOTTOM RIGHT Side 
        * touched the Top Side of the JPanel. 
        */ 
        fromTop = true; 
        fromBottom = false; 
        x -= speedValue; 
        y += speedValue; 
       } 
       else if (fromTop && !fromBottom && x <= 0 && y < height 
           && !toRight && toLeft) 
       { 
        /* 
        * Since the ball coming from the TOP RIGHT Side 
        * touched the LEFT Side of the JPanel. 
        */ 
        toRight = true; 
        toLeft = false; 
        x += speedValue; 
        y += speedValue; 
       } 
       else if (fromTop && !fromBottom && x >= width && y < height 
            && toRight && !toLeft) 
       { 
        /* 
        * Since the ball coming from the TOP LEFT Side 
        * touched the RIGHT Side of the JPanel 
        */ 
        toRight = false; 
        toLeft = true; 
        x -= speedValue; 
        y += speedValue; 
       } 
       else if (fromTop && !fromBottom && x < width && y < height 
            && !toRight && toLeft) 
       { 
        x -= speedValue; 
        y += speedValue; 
       } 
       else if (!fromTop && fromBottom && x <= 0 && y < height 
            && !toRight && toLeft) 
       { 
        /* 
        * Since the ball coming from the BOTTOM RIGHT Side 
        * touched the LEFT Side of the JPanel. 
        */ 
        toRight = true; 
        toLeft = false; 
        x += speedValue; 
        y -= speedValue; 
       } 
       else if (!fromTop && fromBottom && x < width && y < height 
            && !toRight && toLeft) 
       { 
        x -= speedValue; 
        y -= speedValue; 
       } 
       else if (fromTop && !fromBottom && x < width && y >= height 
            && !toRight && toLeft) 
       { 
        /* 
        * Since the ball coming from the TOP RIGHT Side 
        * touched the BOTTOM Side of the JPanel. 
        */ 
        fromTop = false; 
        fromBottom = true; 
        x -= speedValue; 
        y -= speedValue; 
       } 
       System.out.println("X : " + x); 
       System.out.println("Y : " + y); 
       System.out.println("Direction is LEFT : " + toLeft); 
       System.out.println("Direction is RIGHT : " + toRight); 
       System.out.println("Coming from TOP : " + fromTop); 
       System.out.println("Coming from BOTTOM : " + fromBottom); 
       drawPanel.setXYValues(x, y); 
      } 
     }; 

     buttonAction = new ActionListener() 
     { 
      public void actionPerformed(ActionEvent ae) 
      { 
       if (!flag) 
       { 
        timer.start(); 
        button.setText("STOP ANIMATION"); 
        flag = true; 
       } 
       else if (flag) 
       { 
        timer.stop(); 
        button.setText("START ANIMATION"); 
        flag = false; 
       } 
      } 
     }; 

     button = new JButton("START ANIMATION"); 
     button.addActionListener(buttonAction); 

     frame.getContentPane().add(drawPanel, BorderLayout.CENTER); 
     frame.getContentPane().add(button, BorderLayout.PAGE_END); 
     frame.setSize(300, 300); 
     //frame.pack(); 
     frame.setVisible(true);   

     timer = new Timer(40, actionTimer); 
     width = drawPanel.getWidth() - 30; 
     System.out.println("WIDTH : " + width); 
     height = drawPanel.getHeight() - 30;  
     System.out.println("HEIGHT : " + height); 
    } 
    class MyDraw extends JComponent 
    { 
     private int x; 
     private int y; 
     private Timer timer; 

     public MyDraw(int x, int y) 
     { 
      this.x = x; 
      this.y = y; 
     } 

     public int getXValue() 
     { 
      return x; 
     } 

     public int getYValue() 
     { 
      return y; 
     } 

     public void setXYValues(int x, int y) 
     { 
      this.x = x; 
      this.y = y; 
      repaint(); 
     } 

     public Dimension getPreferredSize() 
     { 
      return (new Dimension(300, 300)); 
     } 

     public void paintComponent(Graphics g) 
     { 
      g.setColor(Color.WHITE); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
      g.setColor(Color.BLUE); 
      g.fillOval(x, y, 40, 40); 
     } 
    } 
} 
+2

你知道你的大量if邏輯可以被壓縮到1/4的大小,代碼少得多,對吧?使用x和y速度(可能是負數)將消除布爾標誌,將所有移動代碼轉換爲'x + = xVel; y + = yVel;',然後您只剩下out-of-邊界檢查,將球推回到邊界內,並反轉相關的速度。 – zebediah49 2012-03-21 08:35:57

+0

@ zebediah49:可以請你在你的回答中詳細說明邏輯thingy :-) – 2012-03-21 08:55:22

+2

這是一段7年左右的代碼,所以圖形處理相當不推薦。無論如何,控制和牆壁邏輯是標準的。這是因爲它具有固體(反彈)和週期性(!反彈)邊界條件。 http://pastebin.com/UT8fyAaB – zebediah49 2012-03-21 09:35:49

回答

6

現在,這是一個整個heapin'幫助代碼!嘗試這個變體(打破一兩件事,但解決了主要問題)。解決方法是將寬度/高度基於組件的當前大小。

package test; 

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

public class BallAnimation 
{ 
    private int x; 
    private int y; 
    private int count; 
    //private int drawPanel.getWidth(); 
    //private int drawPanel.getHeight(); 
    private int speedValue; 
    private boolean flag; 
    /* 
    * These variables are used to keep track of 
    * the ball, either it is going LEFT or RIGHT 
    * depending on that, we will set the 
    * Co-ordinates. 
    */ 
    private boolean toLeft, toRight; 

    private boolean fromTop, fromBottom; 

    private Timer timer; 

    private JButton button; 

    private ActionListener actionTimer; 
    private ActionListener buttonAction; 

    MyDraw drawPanel; 

    public BallAnimation() 
    { 
     x = y = count = 0; 
     flag = toLeft = false; 
     toRight = true; 
     fromTop = true; 
     fromBottom = false; 
     speedValue = 5; 
    } 

    public static void main(String args[]) 
    { 
     Runnable runnable = new Runnable() 
     { 
      public void run() 
      { 
       BallAnimation animation = new BallAnimation(); 
       animation.go(); 
      } 
     };  
     SwingUtilities.invokeLater(runnable); 
    } 

    public void go() 
    { 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     //JPanel contentPane = new JPanel(); 

     /* 
     * Class Name : 
     * Java Naming Convention says that class names 
     * should be in Pascal Case, i.e. the first 
     * letter of the class name should be capitalized 
     * and every new word must start with a capitalized 
     * Alphabet. 
     * For Example : 
     * public class ClassName{...} 
     * ---------------------------------------------------------- 
     * Variable Name : 
     * Java Naming Convention says that the variable name 
     * should be in Camel Case, i.e. the first letter of 
     * the variable name should be small case or _ (underscore) 
     * and every new word must start with a capitalized 
     * Alphabet. 
     * --------------------------------------------------------- 
     */ 
     drawPanel = new MyDraw(0, 0); 
     x = drawPanel.getXValue(); 
     y = drawPanel.getYValue(); 
     //contentPane.add(drawPanel); 

     actionTimer = new ActionListener() 
     { 
      public void actionPerformed(ActionEvent ae) 
      {    
       if (fromTop && !fromBottom && x < drawPanel.getWidth() && y < drawPanel.getHeight() 
          && toRight && !toLeft) 
       { 
        x += speedValue; 
        y += speedValue; 
       } 
       else if (fromTop && !fromBottom && x < drawPanel.getWidth() && y >= drawPanel.getHeight() 
           && toRight && !toLeft) 
       { 
        /* 
        * Since the ball coming from the TOP LEFT Side 
        * touched the BOTTOM of the JPanel. 
        */ 
        y -= speedValue; 
        x += speedValue; 
        fromTop = false; 
        fromBottom = true; 
       } 
       else if (!fromTop && fromBottom && x < drawPanel.getWidth() && y <= 0 
            && toRight && !toLeft) 
       { 
        /* 
        * Since the ball coming from BOTTOM LEFT Side 
        * touched the TOP of the JPanel. 
        */ 
        fromTop = true; 
        fromBottom = false; 
        x += speedValue; 
        y += speedValue; 
       } 
       else if (!fromTop && fromBottom && x < drawPanel.getWidth() && y < drawPanel.getHeight() 
            && toRight && !toLeft) 
       { 
        x += speedValue; 
        y -= speedValue; 
       } 
       else if (!fromTop && fromBottom && x >= drawPanel.getWidth() && y < drawPanel.getHeight() 
            && toRight && !toLeft) 
       { 
        /* 
        * Since the ball coming from the BOTTOM LEFT Side 
        * touched the RIGHT Side of the JPanel. 
        */ 
        toRight = false; 
        toLeft = true; 
        x -= speedValue; 
        y -= speedValue; 
       }     
       else if (!fromTop && fromBottom && x < drawPanel.getWidth() && y <= 0 
            && !toRight && toLeft) 
       { 
        /* 
        * Since the ball coming from the BOTTOM RIGHT Side 
        * touched the Top Side of the JPanel. 
        */ 
        fromTop = true; 
        fromBottom = false; 
        x -= speedValue; 
        y += speedValue; 
       } 
       else if (fromTop && !fromBottom && x <= 0 && y < drawPanel.getHeight() 
           && !toRight && toLeft) 
       { 
        /* 
        * Since the ball coming from the TOP RIGHT Side 
        * touched the LEFT Side of the JPanel. 
        */ 
        toRight = true; 
        toLeft = false; 
        x += speedValue; 
        y += speedValue; 
       } 
       else if (fromTop && !fromBottom && x >= drawPanel.getWidth() && y < drawPanel.getHeight() 
            && toRight && !toLeft) 
       { 
        /* 
        * Since the ball coming from the TOP LEFT Side 
        * touched the RIGHT Side of the JPanel 
        */ 
        toRight = false; 
        toLeft = true; 
        x -= speedValue; 
        y += speedValue; 
       } 
       else if (fromTop && !fromBottom && x < drawPanel.getWidth() && y < drawPanel.getHeight() 
            && !toRight && toLeft) 
       { 
        x -= speedValue; 
        y += speedValue; 
       } 
       else if (!fromTop && fromBottom && x <= 0 && y < drawPanel.getHeight() 
            && !toRight && toLeft) 
       { 
        /* 
        * Since the ball coming from the BOTTOM RIGHT Side 
        * touched the LEFT Side of the JPanel. 
        */ 
        toRight = true; 
        toLeft = false; 
        x += speedValue; 
        y -= speedValue; 
       } 
       else if (!fromTop && fromBottom && x < drawPanel.getWidth() && y < drawPanel.getHeight() 
            && !toRight && toLeft) 
       { 
        x -= speedValue; 
        y -= speedValue; 
       } 
       else if (fromTop && !fromBottom && x < drawPanel.getWidth() && y >= drawPanel.getHeight() 
            && !toRight && toLeft) 
       { 
        /* 
        * Since the ball coming from the TOP RIGHT Side 
        * touched the BOTTOM Side of the JPanel. 
        */ 
        fromTop = false; 
        fromBottom = true; 
        x -= speedValue; 
        y -= speedValue; 
       } 
       System.out.println("X : " + x); 
       System.out.println("Y : " + y); 
       System.out.println("Direction is LEFT : " + toLeft); 
       System.out.println("Direction is RIGHT : " + toRight); 
       System.out.println("Coming from TOP : " + fromTop); 
       System.out.println("Coming from BOTTOM : " + fromBottom); 
       drawPanel.setXYValues(x, y); 
      } 
     }; 

     buttonAction = new ActionListener() 
     { 
      public void actionPerformed(ActionEvent ae) 
      { 
       if (!flag) 
       { 
        timer.start(); 
        button.setText("STOP ANIMATION"); 
        flag = true; 
       } 
       else if (flag) 
       { 
        timer.stop(); 
        button.setText("START ANIMATION"); 
        flag = false; 
       } 
      } 
     }; 

     button = new JButton("START ANIMATION"); 
     button.addActionListener(buttonAction); 

     frame.getContentPane().add(drawPanel, BorderLayout.CENTER); 
     frame.getContentPane().add(button, BorderLayout.PAGE_END); 
     frame.setSize(300, 300); 
     //frame.pack(); 
     frame.setVisible(true);   

     timer = new Timer(40, actionTimer); 
     System.out.println("WIDTH : " + drawPanel.getWidth()); 
     System.out.println("HEIGHT : " + drawPanel.getHeight()); 
    } 
    class MyDraw extends JComponent 
    { 
     private int x; 
     private int y; 
     private Timer timer; 

     public MyDraw(int x, int y) 
     { 
      this.x = x; 
      this.y = y; 
     } 

     public int getXValue() 
     { 
      return x; 
     } 

     public int getYValue() 
     { 
      return y; 
     } 

     public void setXYValues(int x, int y) 
     { 
      this.x = x; 
      this.y = y; 
      repaint(); 
     } 

     public Dimension getPreferredSize() 
     { 
      return (new Dimension(300, 300)); 
     } 

     public void paintComponent(Graphics g) 
     { 
      g.setColor(Color.WHITE); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
      g.setColor(Color.BLUE); 
      g.fillOval(x, y, 40, 40); 
     } 
    } 
} 
+0

對不起,我很喜歡這個答案(+ 1),讓事情爲我工作,但正如@ zebediah49指出的,我的代碼是廢話,就邏輯而言,所以似乎添加功能調用它會使情況變得更糟,並伴隨條件檢查。 Thankyou在這個問題上提供的幫助:-) – 2012-03-21 13:11:26

+0

今天,我改變了我的程序的邏輯部分,好像你在回答中所說的那樣,工作得很好,不需要'Listener'類的東西。之前我在做的是檢查x和y在一起,這導致了太多的條件檢查。我分開了兩個,這導致了幾行檢查,以及您的建議完美無瑕地工作:-) Thankyou爲:-) – 2012-03-23 15:48:33

+0

*「改變了我的程序的邏輯部分」*優秀!很高興看到你接受了zebediah49的建議(重構邏輯)。 :) – 2012-03-23 15:54:28

2

到JFrame,使widthheight更新只要窗口尺寸更改。

+0

不,根據我的變體,最好將寬度/高度基於組件的當前大小。 – 2012-03-21 08:47:11

+0

我並不一定不同意,但我很好奇爲什麼每次使用它時都更好一些?(另外,爲什麼不將它分配給本地變量,而不是每次調用它?) – zebediah49 2012-03-21 09:19:29

+0

調用當前大小的花費最小,並且OP指出,當調整大小時當前版本不起作用。使用偵聽器來實現大小的更新是可能的,但是與需要時查詢大小相比,它似乎是一種惡意破解。 – 2012-03-21 09:29:26

4

只是單純的需要addHierarchyBoundsListener(...),你MyDraw對象,即drawPanel,像下面的解釋:

private HierarchyBoundsListener boundsListener = 
           new HierarchyBoundsListener() 
{ 
    public void ancestorMoved(HierarchyEvent he) 
    { 
    } 

    public void ancestorResized(HierarchyEvent he) 
    { 
     JComponent component = (JComponent) he.getComponent(); 
     width = component.getWidth() - 30; 
     height = component.getHeight() - 30; 
    } 
}; 

並把它添加到您的drawPanel對象,你可以這樣做:

drawPanel.addHierarchyBoundsListener(boundsListener); 
+0

這確實使我的一天,添加'HierarchyBoundsListener'。謝謝你的幫助:-) – 2012-03-21 13:15:30