答案归结为您想要实现的目标......
要记住的重要事项是,Swing 是单线程环境,也就是说,所有对 UI 的交互、更改、修改、更新和创建都是在事件调度线程的上下文中完成的。
阻止 EDT 的任何操作(例如sleep
、wait
等)都将阻止 EDT 重新绘制 UI 或响应新事件。
实现这一目标的一种方法是通过使用javax.swing.Timer
这是使用 3 个链接在一起的计时器的非常简单的示例。就个人而言,我会使用为短时间滴答配置的单个计时器并检查是否发生了所需的延迟,然后相应地更改状态,但这得到了重点......
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SimpleTimer {
public static void main(String[] args) {
new SimpleTimer();
}
public SimpleTimer() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Timer red;
private Timer green;
private Timer yellow;
private Color color = Color.GREEN;
private Point spot;
public TestPane() {
red = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
color = Color.RED;
green.start();
repaint();
}
});
green = new Timer(2000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
color = Color.GREEN;
yellow.start();
repaint();
}
});
yellow = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
color = Color.YELLOW;
red.start();
repaint();
}
});
red.setRepeats(false);
green.setRepeats(false);
yellow.setRepeats(false);
green.start();
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
spot = e.getPoint();
repaint();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int radius = 20;
int x = (getWidth() - radius) / 2;
int y = (getHeight() - radius) / 2;
g2d.setColor(color);
g2d.fillOval(x, y, radius, radius);
if (spot != null) {
x = spot.x - 5;
y = spot.y - 5;
g2d.setColor(Color.RED);
g2d.drawOval(x, y, 10, 10);
g2d.setColor(Color.YELLOW);
g2d.fillOval(x, y, 10, 10);
}
g2d.dispose();
}
}
}
另一种选择是使用 a SwingWorker
,这允许在后台线程中进行某种处理(让 EDT 运行),但提供了可以简单地将结果同步回 EDT 的方法。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SimpleTimer {
public static void main(String[] args) {
new SimpleTimer();
}
public SimpleTimer() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Color color = Color.GREEN;
private Point spot;
public TestPane() {
new Switcher().execute();
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
spot = e.getPoint();
repaint();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int radius = 20;
int x = (getWidth() - radius) / 2;
int y = (getHeight() - radius) / 2;
g2d.setColor(color);
g2d.fillOval(x, y, radius, radius);
if (spot != null) {
x = spot.x - 5;
y = spot.y - 5;
g2d.setColor(Color.RED);
g2d.drawOval(x, y, 10, 10);
g2d.setColor(Color.YELLOW);
g2d.fillOval(x, y, 10, 10);
}
g2d.dispose();
}
public class Switcher extends SwingWorker<Void, Color> {
@Override
protected void process(List<Color> chunks) {
color = chunks.get(chunks.size() - 1);
repaint();
}
@Override
protected Void doInBackground() throws Exception {
while (true) {
publish(Color.GREEN);
Thread.sleep(2000);
publish(Color.YELLOW);
Thread.sleep(500);
publish(Color.RED);
Thread.sleep(2000);
}
}
}
}
}
查看Swing 中的并发以获取更多详细信息