使用ActionListener添加新元素

时间:2013-11-04 21:39:14

标签: java swing arraylist jpanel

嘿大家我有一个按钮,应该将新球添加到我设置的ArrayList中。而不是添加一个新的球,它只是加快我已经去过的球。 这个CreateCircle创建了球:

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();
}
}

1 个答案:

答案 0 :(得分:4)

CreateCircle类中的每个字段都是static,这意味着它们在CreateCircle的所有实例之间共享。基本上这意味着你在其中一个球上进行的每一次计算都发生在每个球上,并且每个球都是相同的。

如果您希望这些属性与static的特定实例相关联,则必须使那些不是CreateCircle

您可能希望查看http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html上的实例和班级成员的官方教程。

根据你的问题更新re:闪烁如下:我已经创建了一个弹跳JLabel的例子(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如何绘制你的组件 - 你不需要担心球的位置或者你的{ {1}}实施; Swing已经保持了组件的位置和大小。您只需在组件的坐标系中绘制一个圆圈。