0

大家好,我有一个按钮,可以向我设置的 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();
}
}
4

1 回答 1

4

类中的每个字段CreateCircle都是static,这意味着它们在 a 的所有实例之间共享CreateCircle。从本质上讲,这意味着您对其中一个球所做的每项计算都会发生在每个球上,并且每个球都是相同的。

如果您希望static这些属性与CreateCircle.

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

根据您的问题进行更新:以下闪烁:我创建了一个弹跳 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);
            }
        });
    }

}

例如,如果你想绘制球而不是标签,你可以扩展 eg aJComponent并且代码基本相同,除了你重写paint()以告诉 Swing 如何绘制你的组件——你不需要担心球在您的paint()实施中的位置或类似的东西;Swing 已经保持了组件的位置和大小。您只需要在组件的坐标系中画一个圆圈。

于 2013-11-04T21:44:38.693 回答