2015-03-30 53 views
1

我試圖使用Graphics2D繪製一個JPanel,並且我想在SwingWorker的done()方法中繪製圖形,在doInBackGround()中執行一些數學運算後,但這似乎並沒有繪製任何東西?嘗試從SwingWorker done()方法中繪製JPanel什麼也不做

我的代碼有什麼問題?

class MyJanel extends JPanel { 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(800, 600); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     MyExecutor worker = new MyExecutor(g2); 
     worker.execute(); 
    } 

    class MyExecutor extends SwingWorker<Void,Void> { 

     Graphics2D gRef; 
     int result; 

     public MyExecutor(Graphics2D g2){ 
      gRef = g2; 
     } 

     @Override 
     protected Void doInBackground() { 
      result = 100+100; 
      return null; 
     } 

     @Override 
     protected void done() { 
      gRef.drawLine(20, 20, result, result); 
     } 
    } 

} 
+1

永遠不要保留對Graphics對象的引用(除非你自己創建Graphics)。如果你想觸發'paintComponent()',調用'repaint()'。此外,不要將有狀態代碼放在'paintComponent()'中,因爲你無法確定它將被調用的時間和次數。 – 2015-03-30 20:11:19

+0

'不要保留對Graphics對象的引用(除非你自己創建圖形)'Source please?謝謝 – 2015-04-01 04:34:52

+0

我沒有任何資料來源,只是經驗告訴我,當你這樣做時,你總會遇到問題。當你想到它時,這是非常合乎邏輯的。 – 2015-04-01 11:58:36

回答

3

paintComponent()方法僅用於繪畫!擺脫paintComponent()方法中的SwingWorker代碼。

如果你想繪製一個組件,那麼done()方法應該調用組件上的一個屬性。例如,在你的情況,你正試圖劃清界限,所以在你的paintComponent方法中的代碼可能看起來像:

super.paintComponent(g); 

if (drawLine) 
    g.drawLine(...); 

那麼你會創建這樣的方法:

public void setDrawLine(Boolean drawLine) 
{ 
    this.drawLine = drawLine; 
    repaint(); 
} 

所以在DONE ()方法只需在組件上調用setDrawLine(true)即可。另外,無論何時你做自定義繪畫,你都需要重寫getPreferredSize()方法來返回組件的尺寸,這樣佈局管理器可以使用這些信息,否則尺寸將是(0,0),並且沒有任何東西塗料。有關更多信息和工作示例,請閱讀有關Custom Painting的Swing教程。

也許你還需要一個單獨的方法來啓動組件中的SwingWorker。

編輯:

我改變你的代碼:

@Override 
public void paintComponent(final Graphics g) 
{ 
    super.paintComponent(g); 

    g.drawLine(10, 0, 10, 100); 

    SwingUtilities.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
      g2.drawLine(100, 0, 100, 100); 
     } 
    }); 
} 

這也不起作用。我猜測,因爲代碼被添加到EDT的末尾,所以當它執行Graphics對象時已經被處置了。

+0

'paintComponent()方法僅用於繪畫!擺脫paintComponent()方法中的SwingWorker代碼。「我不覺得它有什麼不好嗎?最後,它只是一種觸發繪圖的方法,在這種情況下,由於SwingWorker的原因,所以在那裏調用它有什麼問題? – 2015-03-30 19:24:06

+0

我的代碼中有'getPreferredSize()',只是我沒有在這個例子中包含,用它更新了代碼。 – 2015-03-30 19:27:32

+1

@jj_,繪畫方法僅用於繪畫。 Swing在確定繪畫需要完成時將調用繪畫方法。您不應該調用任何與繪畫無關的外部功能。 – camickr 2015-03-30 19:40:39