问题
I wrote a simple java program to place some rectangles on the screen (after some delay between each other)
package guitest2;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
public void paintComponent( Graphics g) {
super.paintComponent(g);
for (int i = 0; i < 10; i++ ) {
g.drawRect(10+5*i, 10+5*i, 20, 20);
try{
Thread.sleep( 2000 );
}
catch (InterruptedException ex) { }
}
}
}
I used that class in
package guitest2;
import javax.swing.JFrame;
public class Guitest2 {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame app = new JFrame();
app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
app.add(panel);
app.setSize(450, 250);
app.setVisible(true);
}
}
The problem with running the above code is that, the squares are not shown. After 10*2S = 20 seconds, the final panel is shown containing all squares. What I want are:
1- Draw a square with g.drawRect
.
2- Wait for 2 seconds
3- Remove the previous square and draw the new one.
回答1:
Maybe you could use the code like below, I changed a bit your code with comments.
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class RectTest {
DrawPanel panel;
int x;
int y;
public static void main(String[] args) {
new RectTest().startApp();
}
public void startApp() {
panel = new DrawPanel();
JFrame app = new JFrame();
app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
//modify this line
app.getContentPane().add(panel);
app.setSize(450, 250);
app.setVisible(true);
//added for loop here
for (int i = 0; i < 10; i++ ) {
// x,y here
x = 10+5*i;
y = 10+5*i;
// repaint the panel
panel.repaint();
// wait 2sec
try{
Thread.sleep( 2000 );
}
catch (InterruptedException ex) { }
}
}
class DrawPanel extends JPanel {
public void paintComponent( Graphics g) {
//super.paintComponent(g);
// repaint the backround to see the single reactangles
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.green);
g.drawRect(x, y, 20, 20);
}
}
}
回答2:
You are sleeping on the Event Dispatch Thread (EDT), thereby blocking all GUI related events. The GUI runs on this one thread, the EDT, so you can't block it like that (i.e. sleep in a loop).
A relevant quote from the EDT link:
It's useful to think of the code running on the event dispatch thread as a series of short tasks. [...]
Tasks on the event dispatch thread must finish quickly; if they don't, unhandled events back up and the user interface becomes unresponsive.
In your case, you are drawing 10 rectangles, with some sleeping in between. Then the rest of the event queue is handled. That results in a GUI being stuck for 10 x 2000ms, then the drawing is done.
Instead use a Swing Timer to time GUI related events:
A Swing timer (an instance of javax.swing.Timer) fires one or more action events after a specified delay. [...]
[...] we recommend using Swing timers [...] for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread.
来源:https://stackoverflow.com/questions/41247668/using-sleep-in-jpanel