2013-03-07 33 views
3

我有一個JPanel自定義繪畫執行可能需要長達15秒。畫一個JPanel隱藏菜單

enter image description here

的問題是,當我點擊菜單上,而JPanel的被塗的同時,畫正通過菜單進行和選項是不可見的。 (見圖片中的變形文字)

enter image description here

如果我在菜單上單擊畫完成後,沒有不必要的行爲,但是當我將鼠標指針移動到不同的菜單,同樣的事情發生再次。 例如,完成繪畫後,如果點擊'應用程序',則不會產生副作用,但是當我將鼠標指針移動到'幫助'上時,會顯示前面描述的行爲。 這怎麼能避免?

我的的paintComponent()方法執行外畫在一個單獨的線程:

public class RandomIFSPanel extends JPanel { 

    RandomIFSPanelRenderer randomIFSPanelRenderer; 

@Override 
    public void paintComponent(Graphics graphics) { 
     try { 
      randomIFSPanelRenderer.stop(); 
     } catch (Exception e) { 
     } 
randomIFSPanelRenderer = new RandomIFSPanelRenderer(); 
    randomIFSPanelRenderer.start(); 
} 

    class RandomIFSPanelRenderer extends Thread { 
     @Override 
     public void run() { 
      for (int i = 0; i < numberOfPoints; i++) { 
       Graphics g=getGraphics(); 
      g.setColor(Color.WHITE); 
       g.drawLine........ 
      } 
     } 
    } 

} 
+4

你的線程可能是這裏的問題 - 如果你不這樣做所有在美國東部時間油畫,然後你要求麻煩/怪癖,如硫秒。如果使用'SwingUtilities.invokeLater()',問題是否仍然存在? – berry120 2013-03-07 17:23:37

+2

'Graphics g = getGraphics();'是問題的另一部分。您應該考慮替換「BufferedImage」(顯示在「JLabel」中)的整個繪畫表面,並將長時間運行的工作轉移到「SwingWorker」。 – 2013-03-07 17:40:15

+0

@ berry120如果我使用SwingUtilities.invokeLater(randomIFSPanelRenderer)而不是randomIFSPanelRenderer.start(),則窗口在調整大小時將變得無法響應。 – Ranjith 2013-03-08 10:33:30

回答

0

我不會有方法的paintComponent中運行的線程。我會在paint方法之外的線程。

+0

線程需要JPanel的Graphics對象,所以我需要使用像getGraphics.drawXYZ()這樣的語句,如果我在paint方法外部有該線程,則不能完成這些語句。 – Ranjith 2013-03-08 10:36:12

2

除了說了些什麼有關的事件指派線程:

  • 你叫直接的paintComponent()方法?調用repaint()會更「安全」。
  • 當paintComponent()被調用時,是否可以緩衝圖像,繪製圖像然後在面板上設置?
+0

當用戶點擊'繪製'按鈕時,我打電話給randomIFSPanel.repaint()。 RandomIFSPanel是顯示圖形的窗口的黑白部分。 – Ranjith 2013-03-08 10:30:16

+0

根據用戶輸入的值,整個繪畫需要很長時間。我想要在實時計算每個像素時更新圖像。所以,不可能緩衝圖像。 – Ranjith 2013-03-08 10:31:11

+0

也許可以緩衝圖像並每隔100ms顯示一次結果。如果問題沒有消失,請嘗試在幀中調用repaint()。 – 2013-03-08 13:29:07

2

首先,你不應該在paintComponent()方法啓動一個線程,因爲paintComponent()可以通過repaint()被多次援引。它可能會發生新的線程開始,而以前的線程沒有終止。第二,如果您想要菜單正常繪製,請嘗試在paintComponent()開頭添加super.paintComponent(g)

三,Graphics g = getGraphics();爲什麼不只是使用graphics?由於圖形對象正在改變,你不能假定下一幅繪畫是在同一個舊的圖形對象中完成的。

+0

雖然我沒有在我的問題中說過,但我在開始新的之前首先停止了之前的randomIFSPanelRenderer線程。我在這個問題中修改了我的代碼以反映它。我不明白你的意思是說'爲什麼不使用圖形'。你能詳細解釋一下嗎? – Ranjith 2013-03-08 10:26:15

+0

在paintComponent()的開頭添加super.paintComponent(g)不起作用。 – Ranjith 2013-03-08 10:27:47

+0

@ Ranjith-SR2GF您在'paintComponent()'方法中定義了'圖形'。這是你應該使用的,而不是調用'getGraphics()'。同樣,即使你停止了前一個線程,在'paintComponent()'方法中創建並啓動一個新線程仍然不好。當再次調用時,如何確保前一個線程完成。 – shuangwhywhy 2013-03-09 16:40:21

1
  • 不使用線程將阻塞EDT,而不是所有的事件可能是在屏幕上可見,在某些情況下,只有第一次。最後,使用Swing Timer代替

  • 不要創建任何Object,FileIO,Thread等裏面的paintComponent,也沒有不安全內嘗試 - 追趕 - finally塊

  • 之前創建的任何對象,把那陣列和裏面的paintComponent循環結束掉的對象

  • 的陣列內張貼SSCCE,短,可運行,編譯的,只是畫,所有的對象應被存儲爲局部變量(真實的,任何對你關於二次衰落和縮小(ZoomOut)問題)