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。つまり、それらは のすべてのインスタンス間で共有されますCreateCircle。基本的にこれは、ボールの 1 つに対して行うすべての計算がすべてのボールで行われ、すべてのボールが同じであることを意味します。

staticこれらのプロパティを の特定のインスタンスに関連付ける場合は、それらを not にする必要がありますCreateCircle

http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.htmlにあるインスタンスおよびクラス・メンバーに関する公式チュートリアルを参照してください。

あなたの質問に基づいて更新してください:以下のちらつき:これを行う方法を示し、Swingに再描画などを任せる方法を示すJLabelsのバウンスの例( http://pastebin.com/w1D9H6k2 )を作成しました。ここにもあります:

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 に答える