英文:
Draw shapes with delay
问题
我知道已经有成百上千的帖子,但我就是理解不了…
我有一个非常简单的类,用于绘制一个网格。我想在每个方块之后添加0.2秒的延迟。Thread.sleep不起作用。有什么最简单的方法吗?
public Screen() {
repaint();
}
public void paint(Graphics g) {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
g.drawRect(50 * i, 50 * j, 50, 50);
//添加延迟
}
}
}
英文:
I know there are already hundreds of threads but I just cant understand it..
I have this very simple class thats drawing a grid. I would like to add like a 0.2 second delay after each square. Thread.sleep doesnt work. What is the simplest way?
public Screen() {
repaint();
}
public void paint(Graphics g) {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
g.drawRect(50 * i, 50 * j, 50, 50);
//Add delay
}
}
}
</details>
# 答案1
**得分**: 3
以下是您要求的翻译内容:
最简单的实现延迟绘图的方法是使用 [`Swing Timer`](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html),这是一个不会在执行时阻塞 [EDT](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) 的类。这将允许您创建延迟,而不会阻塞用户界面(使所有内容立即显示)。
您将有一个单独的 `JPanel`,它将在 `paintComponent(...)` 方法中处理绘图,而不是像您在上面的代码中所做的那样在 `paint(...)` 中处理。这个 `JPanel` 将重新绘制来自 [`Shape`](https://docs.oracle.com/javase/7/docs/api/java/awt/Shape.html) API 的每个 `Rectangle` 形状。
```java
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class DelayedDrawing {
private JFrame frame;
private JPanel pane;
private Timer timer;
private int xCoord = 0;
private int yCoord = 0;
private static final int GAP = 10;
private static final int WIDTH_HEIGHT = 10;
private static final int ROWS = 5;
private static final int COLS = 5;
private List<Rectangle> rectangles;
@SuppressWarnings("serial")
private void createAndShowGUI() {
// 创建 JFrame
frame = new JFrame(this.getClass().getSimpleName());
// 创建一个基于 Shape API 的 Rectangle 列表
rectangles = new ArrayList<>();
createRectangle();
// 创建用于绘制每个矩形的 JPanel
pane = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Rectangle r : rectangles) {
System.out.println(r.x + " " + r.y);
g2d.draw(r);
}
}
};
// 启动定时器
timer = new Timer(200, listener);
timer.setInitialDelay(1000);
timer.start();
// 将所有内容添加到 frame
frame.add(pane);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void createRectangle() {
Rectangle r = new Rectangle(xCoord * WIDTH_HEIGHT + GAP, yCoord * WIDTH_HEIGHT + GAP, WIDTH_HEIGHT, WIDTH_HEIGHT);
rectangles.add(r);
}
private ActionListener listener = e -> {
if (xCoord < ROWS) {
if (yCoord < COLS) {
yCoord++;
} else {
yCoord = 0;
xCoord++;
if (xCoord == ROWS) {
timer.stop();
return;
}
}
}
createRectangle();
pane.repaint();
};
public static void main(String[] args) {
SwingUtilities.invokeLater(new DelayedDrawing()::createAndShowGUI);
}
}
希望这对您有所帮助。
英文:
The simplest way to achieve delayed drawing is by using a Swing Timer
, which is a class that won't block the EDT when executed. This will allow you to create a delay without blocking your UI (and making everything appear at once).
You'll have a single JPanel
that's going to handle the painting in the paintComponent(...)
method and not paint(...)
as you did in your code above. This JPanel
will repaint every Rectangle
shape from the Shape
API.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class DelayedDrawing {
private JFrame frame;
private JPanel pane;
private Timer timer;
private int xCoord = 0;
private int yCoord = 0;
private static final int GAP = 10;
private static final int WIDTH_HEIGHT = 10;
private static final int ROWS = 5;
private static final int COLS = 5;
private List<Rectangle> rectangles;
@SuppressWarnings("serial")
private void createAndShowGUI() {
//We create the JFrame
frame = new JFrame(this.getClass().getSimpleName());
//We create a list of Rectangles from the Shape API
rectangles = new ArrayList<>();
createRectangle();
//Creates our JPanel that's going to draw every rectangle
pane = new JPanel() {
//Specifies the size of our JPanel
@Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
//This is where the "magic" happens, it iterates over our list and repaints every single Rectangle in it
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Rectangle r : rectangles) {
System.out.println(r.x + " " + r.y);
g2d.draw(r);
}
}
};
//This starts our Timer
timer = new Timer(200, listener);
timer.setInitialDelay(1000);
timer.start();
//We add everything to the frame
frame.add(pane);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//Creates a new Rectangle and adds it to the List
private void createRectangle() {
Rectangle r = new Rectangle(xCoord * WIDTH_HEIGHT + GAP, yCoord * WIDTH_HEIGHT + GAP, WIDTH_HEIGHT, WIDTH_HEIGHT);
rectangles.add(r);
}
//This will be executed everytime the Timer is fired
private ActionListener listener = e -> {
if (xCoord < ROWS) {
if (yCoord < COLS) {
yCoord++;
} else {
yCoord = 0;
xCoord++;
if (xCoord == ROWS) {
timer.stop();
return;
}
}
}
createRectangle();
pane.repaint();
};
public static void main(String[] args) {
SwingUtilities.invokeLater(new DelayedDrawing()::createAndShowGUI);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论