我无法在调整move方法时让我的shape数组中的每个元素移动。我希望每10毫秒重新绘制一次面板,其形状处于新位置。当我按下启动按钮/启动计时器时,我想这样做。我也希望能够使用我的计时器和Jbutton停止这个。随意请我解释一下:)为你的帮助干杯:)
这是我的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
答案 0 :(得分: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
,这是一个非常糟糕的主意,绘画应该绘制当前状态,并且不应该做任何可能导致任何类型重绘的触发器,否则你将陷入一个无限循环,消耗你的CPU直到什么都不会运行......
请查看How to use Swing Timers了解详情
答案 1 :(得分:0)
您需要将侦听器添加到按钮:
start.addActionListener(listener);
您还应该避免使用相同的侦听器来执行不同的操作。每个按钮和每个Timer应该有自己的监听器,只做按下这个特定按钮时应该发生的事情:
start.addActionListener(new StartMovingActionListener());
stop.addActionListener(new StopMovingActionListener());
timer.addActionListener(new MoveShapesActionListener());
如果您愿意,也可以使用匿名类。但是,一个带有一个大的if / else梯形图来判断whic按钮被按下的单个类是一团糟。