2014-10-26 2 views
0

У меня возникли проблемы с перемещением каждого элемента в моем массиве форм, когда вызывается его метод перемещения. Я хочу, чтобы панель была перерисована каждые 10 миллисекунд с их фигурами на новых позициях. Я хочу сделать это, когда нажата кнопка запуска/таймер. Я также хочу, чтобы остановить это, используя мой таймер и остановку Jbutton. Не стесняйтесь просить меня, чтобы объяснить это больше :) Ура за вашу помощь :)Перемещение массива объекта формы с использованием таймера и кнопки запуска - Java

Вот моя форма класса

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 

ответ

2

У вас есть несколько проблем ...

Во-первых, вы используете ваш ButtonListener с javax.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(); 

     } 
    } 
}); 

Во-вторых, вы на самом деле не зарегистрировать ButtonListener с помощью кнопок start или stop, например. ..

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

в-третьих, вы вызываете repaint в методе paintComponent, это очень плохая идея, пай nting должен рисовать текущее состояние и не должен делать ничего, что в противном случае могло бы вызвать перерисовку любого типа для запуска, иначе вы окажетесь в бесконечном цикле, который потребляет ваш процессор, пока ничего не запустится ...

Посмотрите на How to use Swing Timers для получения более подробной информации

0

Вам необходимо добавить слушателя к кнопке:

start.addActionListener(listener); 

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

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

Вы также можете использовать анонимные классы, если вы предпочитаете. Но один класс с большой лестницей if/else, чтобы узнать, какая кнопка нажата, - это беспорядок.