java - 使用计时器和开始按钮移动形状对象数组 - Java

标签 java arrays graphics timer shapes

当调用其移动方法时,我无法让形状数组中的每个元素移动。我希望每 10 毫秒重新绘制一次面板,并将其形状置于新位置。我想在按下开始按钮/启动计时器时执行此操作。我还希望能够使用计时器和 Jbutton stop 来停止此操作。请随时要求我对此进行更多解释:) 为您的帮助干杯:)

这是我的 Shape 类

import java.util.Random;
import java.awt.*;

public class Shape{
  private int x;
  private int y;
  private int width;
  private int height;
  private Color colour;
  static final int moveX = 1;
  static final int moveY = 1;

    public void move (){
    x = x + moveX;
    y = y + moveY;

  }


  /**randomRange method that takes in two parameters, low and high
    * Creates a Random generator that returns a random integer within the low and high range set
    */
    public class RandomRange{
  public int randomRange(int low, int high){
    Random generator = new Random();
    return generator.nextInt(high-low) + low;

  }
    }
  /**Shape constructor which sets data fields to random values within a range
    */
  public Shape (){

    RandomRange r = new RandomRange();
    this.width = r.randomRange(10, 30); 
    this.height = width;
    this.x = r.randomRange(0,(400-width));
    this.y = r.randomRange(0,(400-height));


    int red = r.randomRange(0,255);
    int green = r.randomRange(0,255);
    int blue = r.randomRange(0,255);
    colour = new Color (red, green, blue); //creates a new Color colour consisting of random values from red,green and blue

  }
  /**Display method that gets passed a graphics object
    *sets graphics object g to colour and fills oval with the random values set in constructor Shape
    */
  public void display(Graphics g){
    g.setColor(colour);
    g.fillOval(x,y,width,height);

  }
} //end of class

ShapePanel 类的开始

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ShapePanel extends JPanel{
  Shape [] shapes = new Shape [20]; //array of 20 elements that have references to as many as 20 Shape objects
  DrawingPanel drawPanel;
  private int count;
  private JPanel controlPanel = new JPanel();
  private JTextField showNum = new JTextField(2);
  private JLabel countLabel = new JLabel("Count"); 
  private JButton addShape = new JButton("Add Shape");
  private JButton start = new JButton("Start");
  private JButton stop = new JButton("Stop");
  Timer timer;
  private final int DELAY = 10;

  /**Main method that creates a new JFrame
    *Adds ShapePanel and does main JFrame methods
    */
  public static void main (String [] args){
    JFrame frame = new JFrame ();
    frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new ShapePanel());
    frame.pack();
    frame.setVisible(true);
  }
  /**ShapePanel constructor that creates a JPanels controlPanel and drawPanel
    * Adds JTextField showNum for display of how many shapes have been created to controlPanel
    * Adds Jlabel count and addShape to controlPanel
    * Adds controlPanel and drawPanel to ShapePanel
    * Sets control Panel to size 100 x 400
    * Makes new ButtonListener called listener and adds the listener to addShape button
    */
  public ShapePanel(){


    ButtonListener listener = new ButtonListener();
    DrawingPanel drawPanel = new DrawingPanel();
    timer = new Timer (DELAY, listener);

    addShape.addActionListener(listener); //adds a new ButtonListener listener to JButton addShape
    controlPanel.add (addShape); //controlPanel adding
    controlPanel.add (showNum);
    controlPanel.add (countLabel);
    controlPanel.add(start);
    controlPanel.add(stop);
    add (controlPanel); 
    add (drawPanel);


    controlPanel.setPreferredSize(new Dimension(100,400)); 
  }
  /**Inner class of ShapePanel that determines action of button being pressed
    *Converts count to string totalCount and sets JTextField to count
    *Creates a new shape every time button is pressed and increments count
    */

  /**Inner class DrawingPanel which contains a constructor and paint method
    */

  private class DrawingPanel extends JPanel{
    /**Contructor that is set to a size of 400 x 400 pixels
      *Background is set to pink
      */
    public DrawingPanel(){
      setPreferredSize(new Dimension(400,400));
      setBackground(Color.pink);

    }

    /**paintComponent method which calls the paintComponenet method from JPanel
      * For every shape that has been created, it calls the display method with graphics object g from Shape class
      * Once display method is called, the repaint method is called
      */
    public void paintComponent(Graphics g){
      super.paintComponent (g);
      for (int index = 0; index< count; index ++){

        shapes[index].display(g);
      }
      repaint();
    } //end of paintComponent
  } //end of DrawingPanel
  private  class ButtonListener implements ActionListener{
    public void actionPerformed (ActionEvent event){
      String totalCount = Integer.toString(count);
      showNum.setText(totalCount);

      if (event.getSource() == addShape && count<shapes.length){
        //check that count is smaler than length of array, if so add new Shape to the array and count ++, set text of JTextField to display count
        //call the repaint method on drawPanel to update panel diplayed on screen
        Shape shape = new Shape();
        shapes [count] = shape;

        count ++;

      }
        if (event.getSource() == start){ //here is my problem! I want to click the start button and be able to move my objects

          timer.start();

          for (Shape shape: shapes){

            shape.move(); 


          }
        }
        if (event.getSource() == stop){
          timer.stop();

        }
         repaint();
      }

  }

}//end of class

最佳答案

你有很多问题......

首先,您将 ButtonListenerjavax.swing.Timer 一起使用,但在监听器中,当计时器到达时,您不执行任何操作来实际更新按钮的位置滴答声。所以而不是...

timer = new Timer(DELAY, buttonListener);

你应该做一些更像......的事情

timer = new Timer(DELAY, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        for (Shape shape : shapes) {

            shape.move();

        }
    }
});

其次,您实际上并未使用 startstop 按钮注册 ButtonListener,例如...

start.addActionListener(buttonListener);
stop.addActionListener(buttonListener);

第三,您在 paintComponent 方法中调用 repaint,这是一个非常糟糕的主意,绘画应该绘制当前状态,并且不应该执行任何可能导致错误的操作。任何类型的重绘都会触发,否则你将陷入无限循环,这会消耗你的 CPU,直到没有任何东西运行......

看看How to use Swing Timers了解更多详情

关于java - 使用计时器和开始按钮移动形状对象数组 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26571631/

相关文章:

javascript - 我可以在 Javascript 中识别(绘图板)Pen Pressure 吗?

javascript - HTML5 canvas 的三种鼠标检测技术,都不够

java - 随机数组生成器 Java

java - 使用 Java 捕获屏幕区域并识别在那里找到的文本

java - JMeter : How to increment dates by +1 within date ranges for every iteration

java - 以编程方式更改联系人图片

java - 使用类方法填充数组

javascript - 从 JSON 数组中删除字段

python - 获取任意长度的所有可能的 str 分区

graphics - Gwt 图形和 ClickHandler