2013-11-04 50 views
0

嘿,大家我有一個按鈕,應該添加一個新的球到我設置的ArrayList。與其添加一個新球,它只是加速我已經有的球。 這CreateCircle創建球:使用ActionListener添加新元素

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

@SuppressWarnings("serial") 
public class CreateCircle extends JPanel { 
/* Ports JFrame width, height from BouncingDrawFrame */ 
static double c, d; 
/* Ports desired size of Circle */ 
static int r = 20; // Initial Value 20 
/* Ports timer delay from BouncingDrawFrame */ 
static int z = 10; // Initial Value 10 
/* Timer to control speed */ 
static Timer t = new Timer(z, null); 
/* X,Y points to start, speed of movement */ 
static double x, y, velX = 1, velY = 1; 
/* Ports color choice from BouncingDrawFrame */ 
static Color myColor; 

public CreateCircle(int a, int b) { 
    /* Height of Frame */ 
    c = a; 
    /* Width of Frame */ 
    d = b; 

    t.start(); 

    t.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) { 
      /* "Bounces" the Ball off the sides */ 
      if (x < 0 || x > (d - (r + 2))) { 
       velX = -velX; 
      } 
      /* "Bounces" the Ball off the top and bottom */ 
      if (y < 0 || y > (c - (r + 30))) { 
       velY = -velY; 
      } 
      /* Moves ball 2 pixels each timer action */ 
      x += velX; 
      y += velY; 
      repaint(); 
     } 

    }); 
} 

public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    Graphics2D g2 = (Graphics2D) g; 
    Ellipse2D circle = new Ellipse2D.Double(x, y, r, r); 
    g2.setColor(myColor); 
    g2.fill(circle); 

} 
} 

雖然這是處理按鈕類,如果點擊創建一個新的球:

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

@SuppressWarnings("serial") 
public class BouncingDrawFrame extends JFrame { 
public BouncingDrawFrame() { 
    /* 
    * Create ArrayList to hold balls, remember ArrayList is not a component 
    * but the elements of ArrayList are 
    */ 
    final ArrayList<CreateCircle> ballList = (ArrayList<CreateCircle>) new ArrayList<CreateCircle>(); 

    /* Create Main Ball Frame */ 
    final JFrame main = new JFrame(); 
    main.setTitle("Bouncing Balls!!"); 
    main.setSize(350, 500); 
    main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    main.setLocationRelativeTo(null); 
    main.setVisible(true); 

    /* Create Control Panel */ 
    JFrame control = new JFrame(); 
    control.setSize(300, 300); 
    control.setTitle("Change Settings!"); 
    control.setLocationRelativeTo(null); 
    control.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    control.setVisible(true); 

    final JPanel p1 = new JPanel(); 
    p1.setLayout(new GridLayout(10, 2)); 
    control.add(p1); 

    final JButton addBall = new JButton("Add A Ball"); 
    p1.add(addBall); 

    /* Y Point */ 
    final int a = main.getHeight(); 
    /* X Point */ 
    final int b = main.getWidth(); 

    ballList.add(new CreateCircle(a, b)); 
    main.add(ballList.get(0)); 

    addBall.addActionListener(new ActionListener() { 
     private int click; 

     public void actionPerformed(ActionEvent arg0) { 
      click++; 
      ballList.add((click), new CreateCircle(a, b)); 
      System.out.println(click); 
      System.out.println(ballList.size()); 
      main.add(ballList.get(click)); 
      repaint(); 
     } 
    }); 
} 
} 

不是創建一個新球,點擊按鈕即可加速第一個球的運動。我正在嘗試向ArrayList的索引添加一個新球,該索引等於所點擊的數量。我有ArrayList的大小和點擊數量輸出到系統,所以我知道ArrayList的大小隨着點擊次數的增加而增加。我只是不知道爲什麼它不添加新的CreateCircle。

PS:這裏是主線程。

public class BouncingRun { 
public static void main(String[] args) { 
    new BouncingDrawFrame(); 
} 
} 
+2

你有一個重要的過度使用靜態修飾符。 **編輯** - 正如我現在看到的那樣,Jason C在回答中說。 1+給他的回答。 –

回答

4

每場在CreateCircle類是static,這意味着它們一個CreateCircle的所有實例之間共享。基本上這意味着你在每個球上進行的每次計算都發生在每個球上,並且每個球都是相同的。

如果您希望那些屬性與CreateCircle的特定實例相關聯,那麼您將不得不使這些屬性成爲static

你可能想看看實例和班級成員的官方教程http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

根據你的問題進行更新re:閃爍如下:我創建了一個反彈JLabels的示例(http://pastebin.com/w1D9H6k2),它展示瞭如何做到這一點,並讓Swing負責重新繪製等等。它也在這裏:

import java.awt.Color; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 


@SuppressWarnings("serial") 
public class BouncingLabels extends JFrame { 

    // this is our bouncing label component. it bounces around its parent. this could 
    // be pulled out into its own class file; its in here to keep the example self 
    // contained. 
    static class BouncingLabel extends JLabel { 

     private int fieldWidth, fieldHeight; // width/height of parent at creation time. 
     private int velX = 1, velY = 1; // current x and y velocity. 

     // constructor sets base label properties and starts a timer. 
     public BouncingLabel (int fieldWidth, int fieldHeight) { 

      this.fieldWidth = fieldWidth; 
      this.fieldHeight = fieldHeight; 

      setBounds(0, 0, 60, 20); 
      setOpaque(true); 
      setBackground(Color.RED); 
      setForeground(Color.WHITE); 
      setText("HELLO"); 
      setVisible(true); 

      // timer will call step() every 10ms. 
      new Timer(10, new ActionListener() { 
       @Override public void actionPerformed (ActionEvent e) { 
        step(); 
       } 
      }).start(); 

     } 

     // step updates the component position. note that no explicit painting is done. 
     private void step() { 

      int x = getX(); 
      int y = getY(); 
      int maxx = fieldWidth - getWidth(); 
      int maxy = fieldHeight - getHeight(); 

      x += velX; 
      y += velY; 

      if ((x >= maxx && velX > 0) || (x <= 0 && velX < 0)) 
       velX = -velX; 
      if ((y >= maxy && velY > 0) || (y <= 0 && velY < 0)) 
       velY = -velY; 

      setLocation(x, y); 

     } 

    } 

    // BouncingLabels is our main frame; click on it to add a label. 
    public BouncingLabels() { 

     // work with the content pane, not the frame itself. 
     final Container c = getContentPane(); 
     c.setPreferredSize(new Dimension(300, 300)); 
     c.setLayout(null); 
     setResizable(false); 
     pack(); 

     // add an initial bouncing object. 
     c.add(new BouncingLabel(c.getWidth(), c.getHeight())); 

     // clicking on the frame will add a new object. 
     addMouseListener(new MouseAdapter() { 
      @Override public void mouseClicked (MouseEvent e) { 
       if (e.getButton() == MouseEvent.BUTTON1) 
        c.add(new BouncingLabel(c.getWidth(), c.getHeight())); 
      }    
     }); 

    } 

    // main method creates and shows a BouncingLabels frame. 
    public static void main (String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override public void run() { 
       BouncingLabels b = new BouncingLabels(); 
       b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       b.setLocationRelativeTo(null); 
       b.setVisible(true); 
      } 
     }); 
    } 

} 

如果你想繪製,例如,球而不是標籤,你可以擴展,例如,一個JComponent和代碼是基本相同的,除了你覆蓋paint()告訴Swing如何繪製你的組件 - 你不需要擔心球的位置或類似於你的paint()實現; Swing已經保存了組件的位置和大小。您只需在組件的座標系中繪製一個圓。

+0

謝謝你的工作,我從所有的變量和字段中刪除了靜態修飾符,但現在當我創建一個新球時,它閃爍。我需要把repaint()放在任何地方嗎? – Sam

+1

你的代碼有很多問題;特別是每次添加'CreateCircle'時,由於它是一個組件,它的幾何由主窗格的佈局管理器決定(順便說一句,您應該添加到'main.getContentPane()',而不是'main')。你實際上在做什麼是創建一堆自定義組件,所有這些組件都佔用了整個框架並相互重疊。您需要重新編寫代碼以依賴更多'JPanel'的現有功能 - 使用底層的JPanel的X,Y,寬度和高度屬性,繪製相對於該屬性的橢圓,並使用空佈局經理。讓Swing完成這項工作。 –

+0

我已經添加了一個例子。 –

相關問題