你不想在EDT上同步或让它加入其他线程,因为这可能会冻结你的程序.可能你最好的选择是使用一个监听器类型的结构来通知Swing代码后台线程已经完成,例如可以通过添加PropertyChangeListenera SwingWorker并监听要更改的"state"属性来完成SwingWorker.StateValue.DONE.如果你确实使用它,请务必get()在你的SwingWorker内部调用,PropertyChangeListener以便捕获可能在后台线程中抛出的所有异常.
编辑
你在评论中说:
但我会试着解释一下.用户按下按钮.我希望一些JPanel对象在按下按钮的同时连续移动到屏幕上的另一个位置.这个动作大约需要0.4秒,我真的不希望任何按钮在此期间响应.移动由坐标变化+ Thread.sleep(5)提供.似乎在Event Dispatch Thread中实现这一动作是不可能的.我对吗?
setEnabled(false).动画完成后撤消此操作.例如:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class MoveBall extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = PREF_W;
private static final int BALL_W = 40;
private static final int BALL_H = BALL_W;
private static final Color BALL_COLOR = Color.red;
public static final int TIMER_DELAY = 20;
private int ballX = BALL_W / 2;
private int ballY = BALL_H / 2;
private BufferedImage ballImg;
private ButtonAction buttonAction = new ButtonAction("Start Animation");
private Timer timer;
public MoveBall() {
ballImg = new BufferedImage(BALL_W, BALL_H, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = ballImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(BALL_COLOR);
g2.fillOval(1, 1, BALL_W - 2, BALL_H - 2);
g2.dispose();
add(new JButton(buttonAction));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (ballImg != null) {
int x = ballX - BALL_W / 2;
int y = ballY - BALL_H / 2;
g.drawImage(ballImg, x, y, null);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name);
int mnemonic = (int)name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
ballX = BALL_W / 2;
ballY = BALL_H / 2;
repaint();
setEnabled(false);
new Timer(TIMER_DELAY, new TimerListener()).start();
}
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (ballX + BALL_W / 2 >= getWidth()) {
stopBall(e);
} else if (ballY + BALL_H / 2 >= getHeight()) {
stopBall(e);
} else {
ballX++;
ballY++;
}
repaint();
}
private void stopBall(ActionEvent e) {
buttonAction.setEnabled(true);
((Timer) e.getSource()).stop();
}
}
private static void createAndShowGui() {
MoveBall mainPanel = new MoveBall();
JFrame frame = new JFrame("MoveBall");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)