我有一個Frame
這是一種顏色,但在角落裏有一些文字。我設置顏色,實際上是從顯示器讀取顏色,然後根據這些測量值進行一些計算。等待AWT重繪完成
問題是,打電話repaint()
導致Frame
被繪後我做的測量。我假設這是由於repaint()
委託給EDT,但由於在實際噴漆工作之前/期間進行的測量,我得到的結果不正確。
我最初的想法是把一個聽衆放在油漆完成上,但我重新刷新更頻繁地比文本更新顏色,我不想聽這些事件。在進行測量之前,我如何等待實際的繪畫任務完成?
我有一個Frame
這是一種顏色,但在角落裏有一些文字。我設置顏色,實際上是從顯示器讀取顏色,然後根據這些測量值進行一些計算。等待AWT重繪完成
問題是,打電話repaint()
導致Frame
被繪後我做的測量。我假設這是由於repaint()
委託給EDT,但由於在實際噴漆工作之前/期間進行的測量,我得到的結果不正確。
我最初的想法是把一個聽衆放在油漆完成上,但我重新刷新更頻繁地比文本更新顏色,我不想聽這些事件。在進行測量之前,我如何等待實際的繪畫任務完成?
令人讚歎,你可以找到...現在
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
PaintEvent pe = (PaintEvent) event;
String type = "";
if (pe.getID() == PaintEvent.PAINT) {
type = "PAINT";
} else if (pe.getID() == PaintEvent.PAINT_FIRST) {
type = "PAINT_FIRST";
} else if (pe.getID() == PaintEvent.PAINT_LAST) {
type = "PAINT_LAST";
} else if (pe.getID() == PaintEvent.UPDATE) {
type = "UPDATE";
}
System.out.println(type + "; pe.UpdateRec = " + pe.getUpdateRect() + "; pe.component = " + pe.getComponent());
}
}, AWTEvent.PAINT_EVENT_MASK);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
,因爲重繪請求可以來思考和快速,我會忍不住放置在一個小的「延遲」將在最後不久解僱請求已完成......
private Timer updateTimer;
// ...
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
updateTimer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Update compulations here...
}
});
updateTimer.setRepeats(false);
updateTimer.setCoalesce(true);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
updateTimer.restart();
}
}, AWTEvent.PAINT_EVENT_MASK);
}
}
的想法是,讓最後的重畫請求和你的編譯的開始之間至少250毫秒。你可能會喜歡擺弄這些值了一下,看看有什麼適合你...
UPDATE
您也可以嘗試在此組件及所有JComponent.paintImmediately
繪製指定的區域其立即與該地區重疊的 後代。
很少有必要調用此方法。在大多數情況下,更高效地調用重繪,這會延遲實際繪畫,並且可以將冗餘請求摺疊爲單個繪畫調用。如果在調度當前事件 時需要更新顯示器,此方法爲 。
我明白你想要做什麼在這裏 - 但你確定他們會按照正確的順序放入EDT嗎?一些測試顯示調用'repaint()'曾經對我的'paint()'方法產生了5次調用,我不知道這些調用是同步的還是添加到事件隊列的末尾。 –
因爲可以重新整理請求,所以不能保證它們會按照您請求的順序顯示。 – MadProgrammer
我不確定您的解決方案如何實際工作。它似乎圍繞着「延遲代碼並希望最好」展開。我錯了嗎? –
您可以同步圍繞匿名鎖對象的線程以使一個線程等待另一個線程。 – Vulcan
我的頭頂,我認爲你不能(可靠地)。您可以嘗試使用'SwingUtilities.invokeLater(Runnable)'在調用重繪後將您的計算放到EDT的尾部,但不能保證在EDT上已經放置了重繪請求... – MadProgrammer
@Vulcan但我無法控制美國東部時間,是嗎?我認爲從實際的角度來看,美聯儲可能是先進先出法,但從正確的角度來看,我確信這一點? –