Re: [問題] 繪圖的兩個問題
※ 引述《the2046 (wz)》之銘言:
: 重畫(repaint)是一件很耗時的工作, 所以它執行的優先權(priority)是最低的.
: 它必需讓其他指令先執行, 它才能執行. 例如:
: import javax.swing.*;
: import javax.swing.event.MouseInputListener;
: import java.awt.Graphics;
: import java.awt.event.MouseEvent;
: class TeachPanel extends JPanel implements MouseInputListener{
: public TeachPanel() {
: this.addMouseListener(this);
: this.addMouseMotionListener(this);
: }
: @Override
: public void paintComponent(Graphics g) {
: System.out.println("paint done");
: System.out.println("----------------");
: }
: public void t() {
: System.out.println("t done1");
: System.out.println("t done2");
: }
: //--------[ implements MouseInputListener
: @Override
: public void mouseDragged(MouseEvent e) {
: System.out.println("drag done1");
: repaint();
: System.out.println("drag done2");
: System.out.println("drag done3");
: System.out.println("drag done4");
: t();
: }
: @Override public void mouseClicked(MouseEvent e) {}
: @Override public void mouseEntered(MouseEvent e) {}
: @Override public void mouseExited(MouseEvent e) {}
: @Override public void mouseMoved(MouseEvent e) {}
: @Override public void mousePressed(MouseEvent e) {}
: @Override public void mouseReleased(MouseEvent e) {}
: //--------] implements MouseInputListener
: public static void main(String[] args) {
: JFrame jf = new JFrame();
: jf.setSize(500, 500);
: jf.setVisible(true);
: jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
: jf.setContentPane(new TeachPanel());
: }
: }
: 輸出結果:
: paint done
: ----------------
: drag done1
: drag done2
: drag done3
: drag done4
: t done1
: t done2
: paint done
: ----------------
: 螢幕初始化時, 系統會自動調用 paintComponent一次,
: 但隨後 repaint()都最後才執行.
會得到這樣的結果主因是 repaint method 本身是 asynchronous operation,它
會造成(觸發) UI 組件的 paint routine 在某個時刻執行(在 event-dispatching
thread),精確地說是 repaint 會 enqueue PaintEvent 到 EDT,造成 paint method
的執行。
因為 mouseDragged method 本身是執行在 EDT 裡,那麼 repaint method 所安排
的 PaintEvent 必定會在 mouseDragged 執行完之後才被處理,於是 paint method
的執行是在 mouseDragged 執行完畢之後,然 mouseDragged method 執行過程裡,
repaint method 被執行的時機則是依照其在 mouseDragged method 裡出現的順序,
換句話說,repaint method 執行的時間點定在 t method 之前。
試著把 mouseDragged method 裡的所有 statemenets 打包到一個 Runnable object
丟到另一個 thread 來執行,你多少可以觀察到 paint method 的執行不是落在最後
的情況。
@Override
public void mouseDragged(MouseEvent e) {
new Thread(new Runnable() {
public void run() {
System.out.println("drag done1");
repaint();
System.out.println("drag done2");
System.out.println("drag done3");
System.out.println("drag done4");
t();
}
}).start();
}
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 218.173.81.225
討論串 (同標題文章)