[英]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
你有很多問題...
首先,將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
按鈕注冊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.