是否有任何方法將Event Dispatch Thread與由swing.Timer
,SwingWorker
或new Thread()
創建的另一個線程同步?我希望EDT等待另一個線程工作(例如,在屏幕上移動對象),並在完成此工作後立即完成一些任務。可能嗎?我必須使用另一個線程,因爲如果我嘗試在EDT中更改對象的座標,我不會在屏幕上看到移動。Swing中的同步
2
A
回答
5
你不想在EDT上同步或讓它加入其他線程,因爲這可能會凍結你的程序。可能最好的辦法是使用監聽器類型的結構來通知Swing代碼後臺線程已完成,例如可以通過將PropertyChangeListener
添加到SwingWorker
並監聽「狀態」屬性更改爲SwingWorker.StateValue.DONE
。如果您確實使用了這種方法,請務必在PropertyChangeListener
的SwingWorker
之內撥打get()
,以便捕獲可能從後臺線程中拋出的所有異常。
編輯
幽州的評論:
但我會盡量解釋。用戶按下按鈕。作爲按鈕按下的結果,我想讓一些JPanel對象不斷移動到屏幕上的另一個地方。這個動作大約需要0.4秒,而我真的不希望任何按鈕在這段時間內響應。運動由座標變化+ Thread.sleep(5)提供。似乎不可能在事件調度線程中實現這種動作。我對嗎?
- 是的,它是完全可能的,如果你使用一個Swing定時器做就EDT運動。擺動計時器使用背景線程在場景後面延遲地重複調用其ActionListener的actionPerformed方法。其使用的關鍵是其actionPerformed方法中的所有代碼在EDT上被稱爲。
- 如果您想取消激活按鈕,請通過調用
setEnabled(false)
將按鈕設置爲禁用1(或更好,它是動作)。動畫完成後撤消此操作。
例如:
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();
}
});
}
}
相關問題
- 1. 通過Socket的Java Swing Timer同步
- 2. 同步Swing Timer與gif圖片
- 3. Java Swing/EDT事件處理同步
- 4. 如何將SwingWorker與Swing同步?
- 5. 在java swing中同步滾動N個jtables
- 6. 如何在Swing中同步請求焦點?
- 7. 的Java Swing,進一步做大,同時發行
- 8. 同步線程中的同步問題
- 9. 同步和java中的同步塊
- 10. 確保Swing GUI與底層數據結構保持同步
- 11. id3中的同步
- 12. Robotium中的同步
- 13. GPU中的同步
- 14. OpenMP中的同步
- 15. ActionScript中的同步
- 16. java jpanel與repaint()或同步同步:是一個Listener可添加到swing的重繪?
- 17. 同步不同步
- 18. 同步不同步
- 19. 在Java swing中重用相同的JPanel
- 20. Java中同步方法ans同步塊
- 21. Java Swing:不同的TableCellRenderers
- 22. 使JavaScript中的異步事件同步
- 23. 異步執行中的同步睡眠?
- 24. 同步Objective-C中的異步任務
- 25. NodeJS中的異步Vs同步
- 26. flex中的同步和異步調用
- 27. javascript中的同步和異步循環
- 28. 在Swift中同步異步的東西
- 29. javaScript中的異步和同步
- 30. 異步代碼中需要的同步
肯定要走的路。使用'SwingWorker'時,在處理結束時會調用'done()'方法 - 這使得在那裏調用回調變得非常容易。 – 2015-02-08 22:26:29
@BoristheSpider:true,但是如果你這樣做,SwingWorker必須對調用代碼有一定的瞭解,因爲它必須調用調用代碼的方法來通知它完成,從而增加耦合。出於這個原因,我通常更喜歡使用PropertyChangeListener。 – 2015-02-08 22:27:22
公平點。使用監聽器確實意味着耦合是單向的。無論哪種方式打敗同步在EDT雖然... – 2015-02-08 22:28:38