Java - удаление моего «червя» из массива и JFrame

1

Моя программа создает случайно окрашенные и размерные черви, которые расширяются на 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;
}
}

Любая помощь очень ценится! :)

EDIT: Это задание, которое мой учитель дал, чтобы написать эту программу.

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

В этом задании собирались написать программу, которая рисует изображения "червей" в окне. Черви будут расти со временем, двигаясь в случайных направлениях. Каждый червь будет другого цвета и будет расти с другой скоростью. Отдельный объект Thread будет управлять чертежом каждого червя. Вот пример того, как будет выглядеть окно после того, как несколько червей выросли на некоторое время.

Напишите класс под названием ThreadFrame, который расширяет JFrame. Этот класс должен включать основной метод, который создает один экземпляр этого класса. Это должно создать графический интерфейс с внешним видом, похожим на то, что вы видите выше. Сделайте окно размером 640 на 480 пикселей и не позволяйте пользователю изменять его размер. Добавьте две области JPanels в область содержимого, белый в центральной области, на которой будут рисоваться нити, и серый в южном регионе, чтобы удерживать кнопки JButtons с надписью "New Worm" и "Kill Worm".

Добавьте исполнитель действия к кнопке "Новый червь", чтобы при щелчке по нему он создавал новый экземпляр класса DrawThread (который будет описан вкратце), добавляет его в ArrayList и запускает его. Добавьте прослушиватель действий к кнопке "Kill Worm", чтобы при нажатии на нее он удаляет первый DrawThread из ArrayList и прерывает его.

Класс DrawThread расширяет поток и выполняет большую часть работы программы. Этот класс будет рисовать на верхней панели ThreadFrame, поэтому ссылка на эту панель должна быть передана конструктору DrawThread, когда этот конструктор вызывается из ThreadFrame. Конструктор должен выполнять следующие задачи:

Назначьте ссылку JPanel (полученную как аргумент) переменной экземпляра этого объекта. Получите графический контекст для JPanel (используйте метод getGraphics), нарисуйте его, чтобы напечатать Graphics2D, и назначьте его переменной экземпляра. Определите ширину и высоту этого JPanel и сохраните эти значения. Создайте объект Color, со случайно выбранными значениями для трех аргументов, чтобы задать интенсивность красного, зеленого и синего, и назначьте этот объект переменной экземпляра. Случайно выберите время сна для этого потока, между 20 и 100 миллисекундами. Это определит, как быстро растет изображение.

  • 3
    Ваш код нарушает правила потоков Swing и будет намного лучше обслуживаться использованием таймера Swing и тем, что вы не будете пытаться делать вызовы Swing в фоновом потоке вне потока событий Swing. Кроме того, вы должны нарисовать либо BufferedImage, который отображается в методе JPCanel paintComponent, либо нарисовать непосредственно внутри метода paintComponent. Ваш способ рисования с помощью вызова getGraphics() для компонента является довольно хрупким и рискованным.
  • 0
    Далее я бы извлек логику червя из GUI. Создайте класс Worm, который содержит всю информацию, необходимую для представления одного объекта Worm, предоставьте ему метод start() , возможно, метод grow() метод stop() method and a kill () `. Затем пусть ваш ActionListener вашего JButton вызывает соответствующие методы, а ActionListener вашего Timer вызывает соответствующие методы. Дайте вашему графическому интерфейсу столько объектов-червей, сколько вам нужно, и подключите кнопки и таймер, чтобы изменить их поведение.
Показать ещё 5 комментариев
Теги:
arraylist
swing
jframe

1 ответ

2
Лучший ответ

Что касается ваших инструкций

Напишите класс под названием ThreadFrame, который расширяет JFrame. Этот класс должен включать основной метод, который создает один экземпляр этого класса. Это должно создать графический интерфейс с внешним видом, похожим на то, что вы видите выше. Сделайте окно размером 640 на 480 пикселей и не позволяйте пользователю изменять его размер. Добавьте две области JPanels в область содержимого, белый в центральной области, на которой будут рисоваться нити, и серый в южном регионе, чтобы удерживать кнопки JButtons с надписью "New Worm" и "Kill Worm".

Хорошо, у тебя это есть.

Добавьте исполнитель действия к кнопке "Новый червь", чтобы при щелчке по нему он создавал новый экземпляр класса DrawThread (который будет описан вкратце), добавляет его в ArrayList и запускает его.

Опять же, вы это сделали.

Добавьте прослушиватель действий к кнопке "Kill Worm", чтобы при нажатии на нее он удаляет первый DrawThread из ArrayList и прерывает его.

Сломай:

  • Получить последний червь из ArrayList - вы бы использовали два метода ArrayList, size() и get(...) для достижения этого. Попробуйте.
  • Затем прервите поток. После того, как вы получите объект из списка массивов, вам нужно будет вызвать метод Thread на нем, и я предполагаю, что вы сможете выяснить, какой метод, правильно (читайте инструкции для этого, то есть "и прерывания" Это")? ;)

редактировать
Обратите внимание, что его рекомендации не очень хорошие, и я бы не нанял вашего инструктора или директора курса в качестве программиста 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();
   }

}
  • 0
    Хаха конечно, конечно. Я полагаю, это зависит от моих навыков понимания ... смеется. Спасибо за всю помощь, которую вы оказали, я буду продолжать с того, что у меня есть.
  • 0
    Я хочу поблагодарить вас за вашу помощь! Я только что закончил успешно прерывать червей, и это работает безупречно! Спасибо!
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню