Java - 从数组列表和 JFrame 中删除我的 'worm'

标签 java swing arraylist jframe

我的程序创建了随机颜色和大小的蠕虫,它们在 JFrame/JPanel 上扩展。随着时间的推移,蠕虫不断向随机方向扩张。当点击新的蠕虫时,屏幕上的某个地方就会诞生一个新的蠕虫。

我的问题出现的地方:

我无法理解如何杀死蠕虫。当我单击“杀死蠕虫”按钮时,我希望蠕虫在屏幕上消失(或停止生长),并将其从数组列表中删除。我什至不知道如何开始这样做。我个人认为删除 arraylist 的实例是最好的方法,但是我如何才能真正从屏幕上删除蠕虫。

下面是我的代码:

主类:

package Main;
import java.awt.Dimension;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
    ThreadFrame myFrame = new ThreadFrame();
    myFrame.setSize(new Dimension(640, 480));
    myFrame.setLocationRelativeTo(null);
    myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    myFrame.setTitle("Worms! - Jonathan Perron");
    myFrame.setVisible(true);
    myFrame.setResizable(false);
}
}

ThreadFrame 类:

package Main;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ThreadFrame extends JFrame implements ActionListener {

int index = 0;
JButton btnNewWorm, btnKillWorm;
JPanel myPanel2 = new JPanel();
ArrayList<DrawThread> worms = new ArrayList<DrawThread>();

public JPanel getMyPanel2(){
    return this.myPanel2;
}

public ThreadFrame() {
    JPanel myPanel = new JPanel();
    btnNewWorm = new JButton("New Worm");
    btnKillWorm = new JButton("Kill Worm");
    myPanel.setBounds(0, 400, 640, 80);
    myPanel.setLayout(new FlowLayout());
    myPanel2.setSize(new Dimension(640, 400));
    myPanel2.setLayout(null);
    myPanel2.setBackground(Color.WHITE);
    btnNewWorm.setBounds(100, 410, 200, 30);
    btnKillWorm.setBounds(340, 410, 200, 30);
    add(btnNewWorm);
    add(btnKillWorm);
    add(myPanel2);
    add(myPanel);
    btnNewWorm.addActionListener(this);
    btnKillWorm.addActionListener(this);
}

public void actionPerformed(ActionEvent AE) {
    if(AE.getSource() == btnNewWorm){
        DrawThread dw = new DrawThread(myPanel2);
        worms.add(dw);
        System.out.println("New worm!");
    }
    if(AE.getSource() == btnKillWorm){ 
        //stop worms from growing or complete disappear from JFrame
        System.out.println("Kill worm!");
    }
}

}

DrawThread 类:

package Main;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.util.Random;
import javax.swing.JPanel;

public class DrawThread extends Thread implements Runnable{

Random rand = new Random();
JPanel panel2 = new JPanel();
Graphics2D g, graph;
private int sleepTime, wormDiameter, hue, saturation, brightness, randomWidth, randomHeight;

public DrawThread(int sleepTime, int wormDiameter, int hue, int saturation, int brightness, int randomWidth, int randomHeight, JPanel myPanel2) {
    this.sleepTime = sleepTime;
    this.wormDiameter = wormDiameter;
    this.brightness = brightness;
    this.hue = hue;
    this.saturation = saturation;
    this.randomWidth = randomWidth;
    this.randomHeight = randomHeight;
    g = (Graphics2D) myPanel2.getGraphics();
}

public void setColor(int hue){
    this.hue = hue;
}

public int getSleepTime(){
    return sleepTime;
}

public void setSleepTime(int sleepTime){
    this.sleepTime = sleepTime;
}
public DrawThread(JPanel myPanel2){

    //get panel dimensions
    int panelWidth = myPanel2.getWidth();
    int panelHeight = myPanel2.getHeight();

    //worm location
    randomWidth = rand.nextInt(panelWidth);
    randomHeight = rand.nextInt(panelHeight);

    //worm size
    wormDiameter = rand.nextInt(7)+3;

    //worm color 
    hue = rand.nextInt(255);
    saturation = rand.nextInt(255);
    brightness = rand.nextInt(255);
    Color color = new Color(hue, saturation, brightness);

    //sleep
    sleepTime = rand.nextInt(80) + 20;

    //Graphics
    g = (Graphics2D) myPanel2.getGraphics();
    g.setColor(color);
    Ellipse2D.Double ellipse2D = new Ellipse2D.Double(randomWidth, randomHeight, wormDiameter, wormDiameter);
    g.fill(ellipse2D);
    Thread thread1 = new Thread(new DrawThread(sleepTime, wormDiameter, hue, saturation, brightness, randomWidth, randomHeight, myPanel2));
    thread1.start();
}

public void run(){
    try { 
        while(true) { 
            Thread.sleep(sleepTime);
            Color color = new Color(hue, saturation, brightness);
            g.setColor(color);
            int addedHeight = 0, addedWidth = 0;
            int random = rand.nextInt(8);

            //determining the worms next move location
            if(random == 0){ addedWidth = 0;  addedHeight = 1;  } //North
            if(random == 1){ addedWidth = 1;  addedHeight = 1;  } //North-East
            if(random == 2){ addedWidth = 1;  addedHeight = 0;  } //East
            if(random == 3){ addedWidth = 1;  addedHeight = -1; } //South-East
            if(random == 4){ addedWidth = 0;  addedHeight = -1; } //South
            if(random == 5){ addedWidth = -1; addedHeight = -1; } //South-West
            if(random == 6){ addedWidth = -1; addedHeight = 0;  } //West
            if(random == 7){ addedWidth = -1; addedHeight = 1;  } //North-West

            //Prevent worms from getting off the screen
            if(randomHeight >= 480){ addedHeight = -1; }
            if(randomHeight <= 0){ addedHeight = 1; }
            if(randomWidth >= 640){ addedWidth = -1; }
            if(randomWidth <= 0){ addedWidth = 1; }

            randomWidth += addedWidth;
            randomHeight += addedHeight;
            Ellipse2D.Double e = new Ellipse2D.Double(randomWidth, randomHeight, wormDiameter, wormDiameter);
            g.fill(e);
            }
    } 
    catch (InterruptedException e) {
        System.out.println("ERROR!");
    }
}

public String toString() {
    String result = "SleepTime: " + sleepTime + "\nWorm Diameter: " + wormDiameter
            + "\nHue: " + hue + "\nSaturation: " + saturation + "\nBrightness: "
            + brightness + "\nWidth: " + randomWidth + "\nHeight: " + randomHeight;
    return result;
}
}

非常感谢任何帮助! :)

编辑:这是我的老师布置的编写这个程序的作业。

================================================== =============================

在这个作业中,我们将编写一个程序,在窗口中绘制“蠕虫”图像。这 蠕虫会随着时间的推移而生长,向随机方向移动。每条蠕虫都有不同的颜色,并且会 以不同的速度增长。一个单独的 Thread 对象将管理每个蠕虫的绘制。这是一个 两条蠕虫生长一段时间后窗口的外观示例。

编写一个名为 ThreadFrame 的类来扩展 JFrame。这个类应该包含一个 main 方法 创建该类的一个实例。这应该会生成一个外观与您所看到的类似的 GUI 多于。将窗口设置为 640 x 480 像素,并且不允许用户调整其大小。添加两个 JPanel 到 内容 Pane ,中间区域有一个白色的,将在其上绘制线程,而在 南部区域持有标有“新蠕虫”和“杀死蠕虫”的 JButton。

向“New Worm”按钮添加一个 Action 监听器,以便当您单击它时,它会创建一个新实例 一个名为 DrawThread 的类(稍后描述),将其添加到 ArrayList 中,并启动它。添加一个 Action 监听“Kill Worm”按钮,这样当您单击它时,它就会从其中删除第一个 DrawThread ArrayList 并中断它。

DrawThread 类扩展了 Thread,并完成了程序的大部分工作。这个类会画 在 ThreadFrame 的上部面板上,因此必须将此面板的引用传递给构造函数 当从 ThreadFrame 调用此构造函数时,会调用 DrawThread 的方法。构造函数应该执行 以下任务:

将 JPanel 引用(作为参数接收)分配给该对象的实例变量。 获取 JPanel 的图形上下文(使用 getGraphics 方法),将其转换为 Graphics2D 类型,然后 将其分配给实例变量。 确定此 JPanel 的宽度和高度,并保存这些值。 创建一个 Color 对象,使用随机选择的三个参数值来设置红色、绿色和 蓝色强度,并将该对象分配给实例变量。 随机选择该线程的 sleep 时间,介于 20 到 100 毫秒之间。这将决定 图像增长的速度有多快。

最佳答案

关于您的指示

Write a class called ThreadFrame that extends JFrame. This class should include a main method that creates one instance of this class. This should produce a GUI with an appearance similar to what you see above. Make the window 640 by 480 pixels, and do not allow the user to resize it. Add two JPanels to the content pane, a white one in the center region on which the threads will be drawn, and a gray one in the south region to hold the JButtons marked “New Worm” and “Kill Worm”.

好的,你已经明白了。

Add an action listener to the “New Worm” button, so that when you click on it, it creates a new instance of a class called DrawThread (to be described shortly), adds it to an ArrayList, and starts it.

再说一次,你已经做到了。

Add an action listener to the “Kill Worm” button, so that when you click on it, it removes the first DrawThread from the ArrayList and interrupts it.

分解:

  • 从 ArrayList 中获取最新的蠕虫 - 您可以使用两个 ArrayList 方法:size()get(...) 来实现此目的。尝试一下。
  • 然后中断线程。一旦从数组列表中获取了对象,您将需要对其调用 Thread 方法,我猜您将能够找出哪个方法,对吧(阅读相关说明,即“和 < em>打断它”)? ;)
<小时/>

编辑
请注意,他的建议并不好,如果我需要的话,我不会聘请您的讲师或类(class)主管作为 Swing 程序员。

<小时/>

编辑
只是为了笑一下,这是编码此类事情的另一种方法。请注意,它不满足您的作业要求(这是我毫不犹豫地发布它的原因之一),但它显示了我认为更好的 Swing 行为:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.*;

public class MyWormMain {

   private static void createAndShowGui() {
      MyWormDrawPanel drawPanel = new MyWormDrawPanel();
      MyWormButtonPanel btnPanel = new MyWormButtonPanel(drawPanel);

      JFrame frame = new JFrame("Worms");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(drawPanel, BorderLayout.CENTER);
      frame.getContentPane().add(btnPanel.getMainPanel(), BorderLayout.SOUTH);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class MyWormDrawPanel extends JPanel {
   private static final int PREF_W = 640;
   private static final int PREF_H = 480;
   private static final Color BACKGROUND = Color.WHITE;
   private static final int TIMER_DELAY = 50;
   private List<MyWorm> wormList = new ArrayList<>();
   private Timer wormTimer;
   private Random random = new Random();

   public MyWormDrawPanel() {
      setBackground(BACKGROUND);
      wormTimer = new Timer(TIMER_DELAY, new WormTimerListener());
      wormTimer.start();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      for (MyWorm worm : wormList) {
         worm.draw(g2);
      }
   }

   public void addWorm() {
      int r = random.nextInt(128) + 128;
      int g = random.nextInt(128) + 128;
      int b = random.nextInt(128) + 128;

      int rand = random.nextInt(3);
      switch (rand) {
      case 0:
         r /= 3;
         break;
      case 1:
         g /= 3;
         break;
      case 2:
         b /= 3;

      default:
         break;
      }
      Color color = new Color(r, g, b);

      int x = random.nextInt(PREF_W);
      int y = random.nextInt(PREF_H);
      Point head = new Point(x, y);
      wormList.add(new MyWorm(color, head, PREF_W, PREF_H));
   }

   public void killWorm() {
      if (wormList.size() > 0) {
         wormList.remove(wormList.size() - 1);
      }
   }

   private class WormTimerListener implements ActionListener {
      public void actionPerformed(ActionEvent e) {
         for (MyWorm worm : wormList) {
            worm.grow();
         }
         repaint();
      };
   }
}

@SuppressWarnings("serial")
class MyWormButtonPanel {
   private static final int GAP = 15;
   private JPanel mainPanel = new JPanel();
   private MyWormDrawPanel drawPanel;

   public MyWormButtonPanel(MyWormDrawPanel drawPanel) {
      this.drawPanel = drawPanel;
      mainPanel.setLayout(new GridLayout(1, 0, GAP, GAP));
      mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
      mainPanel.add(new JButton(new AddWormAction("Add Worm", KeyEvent.VK_A)));
      mainPanel.add(new JButton(new KillWormAction("Kill Worm", KeyEvent.VK_K)));
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }

   private class AddWormAction extends AbstractAction {

      public AddWormAction(String name, int mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         drawPanel.addWorm();
      }
   }

   private class KillWormAction extends AbstractAction {

      public KillWormAction(String name, int mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         drawPanel.killWorm();
      }
   }

}

class MyWorm {
   private static final int MAX_DIR = 360;
   private static final int SEG_WIDTH = 20;
   private static final int MAX_RAND_DIR = 60;
   private Color color;
   private List<Point> body = new ArrayList<>();
   private Random random = new Random();
   private int direction;
   private int maxX;
   private int maxY;

   public MyWorm(Color color, Point head, int maxX, int maxY) {
      this.color = color;
      body.add(head);
      direction = random.nextInt(MAX_DIR);
      this.maxX = maxX;
      this.maxY = maxY;
   }

   public void grow() {
      Point lastPt = body.get(body.size() - 1);
      int x = lastPt.x
            + (int) (SEG_WIDTH * 3 * Math.cos(Math.toRadians(direction)) / 4.0);
      int y = lastPt.y
            + (int) (SEG_WIDTH * 3 * Math.sin(Math.toRadians(direction)) / 4.0);

      if (x < 0) {
         x = maxX - 1;
      } 
      if (x > maxX) {
         x = 0;
      }
      if (y < 0) {
         y = maxY - 1;
      }
      if (y > maxY) {
         y = 0;
      }

      Point nextPoint = new Point(x, y);
      direction += random.nextInt(MAX_RAND_DIR) - MAX_RAND_DIR / 2;

      body.add(nextPoint);
   }

   public void draw(Graphics2D g2) {
      Graphics2D g2b = (Graphics2D) g2.create();
      g2b.setColor(color);
      for (Point p : body) {
         int x = p.x - SEG_WIDTH / 2;
         int y = p.y - SEG_WIDTH / 2;
         int width = SEG_WIDTH;
         int height = SEG_WIDTH;
         g2b.fillOval(x, y, width, height);
      }
      g2b.dispose();
   }

}

关于Java - 从数组列表和 JFrame 中删除我的 'worm',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24706156/

相关文章:

android - 使用集合的字符串 ArrayList

android - 如何避免数组列表事件监听器的内存泄漏?

java - GreenRobot 和 Guava 的 EventBus 使用反射吗?

java - PrintWriter 到 JTextArea,在调用的方法关闭之前不会显示任何内容

java - 如何从 JAX-WS Web 服务中访问 ServletContext?

Java AWT fillOval() 不起作用

java - JPanel上绘制对象的持久化

java - HashSet 与 ArrayList

java - 使用 sql 查询在 hibernate 中创建一个新的对象实例

java - 编写一个按 DMAS 顺序执行运算的计算器