我很想学习如何完成这个项目。我想以随机的颜色和位置绘制三个随机形状,并将它们添加到列表中(稍后需要在第二个窗口中播放)。
这是我所拥有的:
public
class Frame extends JFrame { // here was implements Runnable when i
// used Thread
public ArrayList<MyShape> shapesList = new ArrayList<MyShape>(30); // create list
public JPanel shapePanel;
public Timer timer;
public final int NEW_SHAPE_FREQUENCY = 1000;
public Rectangle myRect;
public Oval myOval;
public Line myLine;
public Frame() {
super("I do not need title, just 50%");
setSize(800, 600);
setDefaultCloseOperation(3);
setLocationRelativeTo(null);
setVisible(true);
setLayout(new BorderLayout());
shapePanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (MyShape s : shapesList) {
g.setColor(myOval.color); // in this line i have
// Exception: NullPointerException
g.fillRect(((int)(getWidth()*Math.random()*0.8d)),((int)
(getHeight()*Math.random()*0.8d)), (int) (myRect.x2),(int) myRect.y2);
}
}
};
add(shapePanel);
initTimer();
// Thread t0 = new Thread(this); // How can i use Threads in this case ??
// t0.start();
}
private void initTimer() {
timer = new Timer(NEW_SHAPE_FREQUENCY, e -> {
shapesList.add(new MyShape()); // Add a new shape to the arraylist
shapePanel.repaint(); // Repaint the panel, so the new shape is
// visible
});
timer.start();
}
/*
@Override
public void run() {
while (true) {
try {
Random rand = new Random();
switch (rand.nextInt(3)+1) {
case 1:
shapesList.add((Shape)myRect);
break;
case 2:
shapesList.add((Shape)myOval);
break;
case 3:
shapesList.add((Shape)myLine);
break;
}
repaint();
Thread.sleep(1000);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
*/
}
修改后,Frame类现在看起来像这样。我是Java新手,对此错误感到抱歉
答案 0 :(得分:0)
首先,花一些时间阅读multiple jframes is good or bad practice。之后,请阅读how to use Swing Timers,以了解如何使它每秒绘制一个新形状(我不确定是否要使用此功能,但看起来确实如此)。如果在Swing应用程序中使用Thread.sleep()
方法,则由于线程处于休眠状态,因此整个GUI将冻结,并且事件将无法发生。
您提供给我们的代码不是Short, Self Contained, Correct (Compilable), Example,因为我们必须对其进行编辑才能使其运行。因此,我创建了一个示例,以向您展示我在实践中的意思。不要忘记在代码内注释注释。
代码:
public class RandomShape extends JFrame {
private static final long serialVersionUID = 6617760910198114903L;
private static final int NEW_SHAPE_FREQUENCY = 1000; // every second new shape
private List<Shape> shapes = new ArrayList<>(); // Keep the shapes
private JPanel shapePanel;
private Timer timer; //A javax.swing.Timer
public RandomShape() {
super("Random shapes");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout()); // set border layout to the content pane
shapePanel = new JPanel() {
/*
* Override paint component in order to add custom painting to this panel. But
* of course, start by calling super.paintComponent()
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Shape s : shapes) {
g.setColor(s.color);
g.fillRect(s.x, s.y, s.width, s.height);
}
}
};
// Add it to the center of the border layout in order to take all window space
add(shapePanel, BorderLayout.CENTER);
setSize(400, 400);
setLocationRelativeTo(null);
initTimer();
}
private void initTimer() {
timer = new Timer(NEW_SHAPE_FREQUENCY, e -> {
shapes.add(new Shape()); // Add a new shape to the arraylist
shapePanel.repaint(); // Repaint the panel, so the new shape is visible
});
timer.start();
}
private static class Shape {
private int x, y, height, width;
private Color color;
private Shape() {
x = random(300);
y = random(300);
height = random(50);
width = random(50);
color = new Color(random(255), random(255), random(255));
}
private static int random(int max) {
return (int) (Math.random() * max);
}
}
public static void main(String[] args) {
// Start application in its own thread, called Event Dispatch Thread.
// For more info, read
// https://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(() -> new RandomShape().setVisible(true));
}
}
预览: