【问题标题】:Multiple Moving Balls: Adding Ball works but removing does not [duplicate]多个移动球:添加球有效但移除无效[重复]
【发布时间】:2014-07-24 08:31:49
【问题描述】:

我正在自学 Java,但在图形方面遇到了一些问题。我从 StackOverflow 中学到了很多东西!如果不是之前的帖子,我会更早发布!

这是基本场景。我有JFrame,我在上面添加了Balls(这是另一个扩展JPanel的类)。球随机移动,一个球在矩形上移动。面板上有三个按钮:暂停、添加随机球和删除随机球。我在移除球时遇到问题。它提供了对ArrayList 的并发访问例外,我不知道如何解决这个问题。

我也想把暂停按钮变成暂停/播放,但不知道如何重新启动运行方法,因为它不是静态方法。

由于我是 Java 新手,我可能会犯一些基本错误,或者我的方法可能不正确。任何建议将不胜感激。谢谢!

代码如下:

球类

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JPanel;

public class Balls extends JPanel {

    public static ArrayList<Balls> BallList = new ArrayList<Balls>();

    public Balls(String n, Color col, String nm) {
        mode = n;
        ballcolor = col;
        name = nm;
        if (name != "dummy") {
            BallList.add(this);
        }

    }

    @Override
    protected void paintComponent(Graphics g) {
        // TODO Auto-generated method stub
        super.paintComponent(g);

        for (Balls ball : BallList) {
            g.setColor(ball.ballcolor);
            g.fillOval(ball.x, ball.y, 20, 20);
        }

    }

    private int x, y;
    private String name;
    private static Boolean run = true;
    public String mode;
    public Color ballcolor;
    private String DirectionR = "R";

    private void getposition() {

        if (mode.equals("Circle")) {
        }

        if (mode.equals("Rectangle")) {
            if (x == 0) {
                x = 150;
            }

            if (y == 0) {
                y = 200;

            }

            if (x == 150 && y == 200) {
                DirectionR = "R";

            }

            if (x == 350 && y == 200) {
                DirectionR = "D";

            }

            if (x == 350 && y == 300) {
                DirectionR = "L";

            }

            if (x == 150 && y == 300) {
                DirectionR = "U";

            }

            if (DirectionR.equals("R")) {
                x++;
            }

            if (DirectionR.equals("L")) {
                x--;
            }

            if (DirectionR.equals("U")) {
                y--;
            }

            if (DirectionR.equals("D")) {
                y++;
            }

        }

        if (mode.equals("Random")) {
            x = (int) (Math.random() * 400);
            y = (int) (Math.random() * 400);
        }

    }

    public void run() {

        while (run == true) {

            for (Balls ball : BallList) {
                ball.getposition();
            }

            try {
                Thread.sleep(20);
            } catch (InterruptedException e2) {
                // TODO: handle exception
                e2.printStackTrace();
            }
            repaint();
        }

    }

    static class pauseframe implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            if (run.equals(true)) {
                run = false;
            }

            else {
                run = true;
            }
        }
    }

    static class addball implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            Balls Randn = new Balls("Random", Color.GREEN, "NEW ADDED");
            for (Balls ball : BallList) {
                System.out.println(ball.name);
            }
        }
    }

    static class Delball implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub

            for (Balls ball : BallList) {
                System.out.println(ball.mode);
                if (ball.mode.equals("Random")) {
                    BallList.remove(ball);
                }

            }
        }
    }
}

测试人员类

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;

public class Balls_test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        JFrame frame = new JFrame();
        Balls dummy = new Balls("Dummy", Color.BLACK, "dummy");
        frame.setSize(500, 500);
        frame.getContentPane().add(dummy);
        frame.setBackground(Color.WHITE);
        dummy.setBackground(Color.WHITE);

        Balls Rect = new Balls("Rectangle", Color.RED, "Rect");

        Balls Rand = new Balls("Random", Color.BLUE, "Rand");

        Button pause = new Button("Pause");
        ActionListener pauseall = new Balls.pauseframe();
        pause.addActionListener(pauseall);
        frame.getContentPane().add(BorderLayout.NORTH, pause);

        Button addRandom = new Button("Add Random Ball");
        ActionListener NewBall = new Balls.addball();
        addRandom.addActionListener(NewBall);
        frame.getContentPane().add(BorderLayout.SOUTH, addRandom);

        Button DelRandom = new Button("Remove Random Ball");
        ActionListener DelBall = new Balls.Delball();
        DelRandom.addActionListener(DelBall);
        frame.getContentPane().add(BorderLayout.WEST, DelRandom);

        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        dummy.run();

    }

}

【问题讨论】:

  • 遵循 Java 命名约定。变量名不应以大写字符开头。你的一些名字是正确的,有些不是!保持一致!

标签: java swing


【解决方案1】:

您无法在迭代代码中使用的 List 时删除该项目:

public static ArrayList<Balls> BallList = new ArrayList<Balls>();

for (Balls ball : BallList) {
    System.out.println(ball.mode);
    if (ball.mode.equals("Random")) {
         BallList.remove(ball); 
    }
}

您应该在迭代列表时使用Iterator 删除项目。

示例代码:

Iterator<Balls> it = BallList.iterator();

while(it.hasNext()) {
    Balls ball = it.next();
    System.out.println(ball.mode);
    if (ball.mode.equals("Random")) {
        it.remove();
    }
}

【讨论】:

  • +1 当没有“随机”球添加到列表中时,我很难理解 OP 如何获得异常:P
  • @MadProgrammer 这是我的荣幸。谢谢。
【解决方案2】:
  1. 您的添加操作不会将球添加到球列表中,因此列表中没有“随机”球
  2. if (name != "dummy") { 不是 String 比较在 Java 中的工作方式
  3. 您不能从 List 中删除一个元素,当它被迭代时。您可以使用synchronized 块来确保一次只有一个线程在访问List,但使用Iterator 来迭代List 可能更容易

【讨论】:

  • 感谢 MadProgrammer.. 我通过获取“随机”球的索引来修复代码,从循环中中断,然后在循环后将其删除。这解决了这个问题。迭代器听起来也不错。也修复了字符串比较。顺便说一句,我在执行 main 方法时添加了随机球,所以当我点击随机球移除按钮时随机球会在那里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-18
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多