2013-04-02 38 views
4

我正在編寫一個簡單的Java Swing應用程序,該應用程序是作爲課程的演示而設計的。該程序的目的是可視化遞歸方法(特別是迷宮的遞歸解決方案)的進展。我希望能夠在遞歸方法執行時更新JComponent的外觀,因此從Swing的角度來看,更新不能單獨從Timer類中觸發,我收集的是用於動畫的常用方法。Swing事件處理程序中的無閃爍JComponent渲染

我的第一個想法是隻要在重繪可視化文件時調用repaint()。但遞歸方法本身在JButton的事件處理程序中調用,這意味着所有對repaint()的調用都會延遲,直到事件處理程序終止 - 而我所看到的只是動畫的最後一幀。我發現,我能得到繪圖立即如果我叫update()方法,而不是發生,就象這樣:

getRootPane().getContentPane().update(getGraphics()); 
try { 
    Thread.sleep(25); 
} catch (Exception e) { 
} 

這幾乎工程,除了動畫閃爍。我知道Swing是雙緩衝的,但顯然getGraphics給了我活動緩衝區而不是後臺緩衝區。我看不到任何方法可以讓我訪問後臺緩衝區。

所以我正在尋找一個解決方案,讓我在遞歸中間重繪組件,並給我一個無閃爍的動畫。有沒有辦法在事件處理程序執行時激活內置的雙緩衝?嘗試實現我自己的緩衝系統會更好嗎?或者,我正在試圖做什麼不可能/建議與Swing?我試着寫一個很好的問題,但是如果我錯過了任何東西,請讓我知道,我會盡力做得更好。下次我會盡力做得更好。謝謝!)

+0

我認爲你已經包括了所有東西:)雖然它可能有助於看到遞歸試圖找出一個重繪()可能會擠入的地方。您可能最終在遞歸中有一些條件和/或重新繪製,以便只在適當時調用它。 – CodeGuy

+0

爲什麼不保留對前一個緩衝區的引用並用它更新? – Redandwhite

回答

2

首先,你應該not be executing long-running actions in the Event Dispatch Thread,我認爲這是動畫閃爍的原因之一。

所以我建議從按下按鈕時開始執行遞歸方法的線程(也許停用它直到工作完成)。

要渲染動畫,您可以從您的遞歸方法中調用myComponent.repaint()或啓動一個Swing計時器(感謝@mKorbel爲poiting了這一點),這基本上是這樣的:

ActionListener repaintTrigger = new ActionListener() { 
     public void actionPerformed(ActionEvent evt) { 
      myComponent.repaint(); 
     } 
}; 
new Timer(25, repaintTrigger).start(); 

我建議後一種方法,因爲你的遞歸方法可能不知道Swing組件的任何內容(除非你通過「ProgressListener」或其他東西解耦它)。

因爲它似乎不僅僅是初學者,我只是提供了一些關於如何做的提示。如果您需要更多的意見,請隨時詢問。

+0

謝謝;這足以讓我繼續前進。關鍵的見解是,在另一個線程上運行遞歸將允許repaint()正常使用。我也喜歡你的其他建議,儘管我試圖保持其餘的代碼簡單,以便遞歸仍然是焦點。 – nhowe

+0

不,永遠不會(當然可以工作),但是使用Swing Timer來取代今天的Java6/7而不是 – mKorbel

+0

@mKorbel在最後幾年裏,我一直沒有做太多的工作,謝謝指點我['javax.swing.Timer'] (http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html) – skirsch

0

我真的不知道這是否工作,但。 我會嘗試使它成爲多線程,並從圖形中分離遞歸。我不知道這是否適用於java,但它在C#中對我有用。