簡體   English   中英

使用計時器和開始按鈕移動形狀對象的數組-Java

[英]Moving an array of shape object using timer and a start button - Java

當調用其移動方法時,我很難讓形狀數組中的每個元素都移動。 我希望面板每隔10毫秒重新繪制一次,其形狀在新位置。 我想在按下啟動按鈕/啟動計時器時執行此操作。 我還希望能夠使用計時器和Jbutton停止功能停止該操作。 請隨時讓我解釋一下更多:)為您的幫助加油:)

這是我的形狀課

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();

        }
    }
});

其次,您實際上ButtonListenerstartstop按鈕注冊ButtonListener ,例如...

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

第三,您要在paintComponent方法中調用repaint ,這是一個非常糟糕的主意,painting應該繪制當前狀態,並且不應該執行任何可能導致任何形式的repaint觸發的操作,否則您將陷入無限循環,這會消耗您的CPU直到什么都不會運行...

看看如何使用Swing計時器了解更多詳細信息

您需要將偵聽器添加到按鈕:

start.addActionListener(listener);

您還應該避免使用相同的偵聽器來執行不同的操作。 每個按鈕和每個計時器都應具有自己的偵聽器,該偵聽器僅執行按下此特定按鈕時應執行的操作:

start.addActionListener(new StartMovingActionListener());
stop.addActionListener(new StopMovingActionListener());
timer.addActionListener(new MoveShapesActionListener());

如果願意,還可以使用匿名類。 但是,一個只有很大的if / else梯子才能知道按下了哪個按鈕的類是一團糟。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM