2010-01-30 106 views
3

我有一個小的Java應用程序有效地「尾巴」在ini文件中定義的任意文件集合。我的「LogReader」類擴展了JFrame,並完成了繁重的工作。將文件路徑的集合讀入向量,然後遍歷向量,讀取每個文件並將每個文件的最後X行添加到JTabbedPane選項卡上的文本區域。通過點擊一個JButton,通過一個ActionListener來啓動構建向量並遍歷文件的過程。Swing「阻塞」,我想我需要線程,但不知道多少

對文件的讀取工作正常(但仍然有效),但是讀取20個文件的過程需要一些時間,其中一些文件增長到30MB。爲了幫助消磨時間,我決定添加一個進度屏幕,其中顯示「正在讀取文件#3/26:c:\ logs \ superduper1.log」等。所以我創建了另一個類「SplashScreen」,它也擴展了JFrame,並添加了一個JLabel來指示進度。 SplashScreen類有一個update()方法,它只是在JLabel上執行setText()。

上的JButton的ActionListener的調用RefreshLogs(),它看起來像:

vctFileStrings.clear(); 
tpMain.removeAll(); 
frmSplash.update("Loading Configuration"); //Update the label on the Splash Screen instance 
BuildVectorOfLogs(strConfFile); //Read the collection of files into the vector 
frmSplash.update("Reading Logs"); 
ReadLogs(); //read the files, updating the Splash Screen as we go 

,然後ReadLogs()在矢量迭代,讀取文件和建設的TabbedPane。

但我注意到,當從ActionListener中調用RefreshLogs()時,Splash Screen不會更新。但是,如果將RefreshLogs()添加到第一幀的構造函數中,則初始屏幕將按預期工作(每個文件都會更新進度)。經過一些實驗和閱讀後,我認爲我需要創建一個讀取文件的工作線程,同時更新事件派發隊列中的啓動畫面。

我的問題是:
- 我的想法是否正確?是否有一些簡單的替代方案來實現線程,這將允許我從ActionListener調用的方法更新啓動畫面?
- 如果使用線程可以最好地完成此操作,那麼我需要線程的活動範圍是什麼?我需要將所有的文件I/O活動放到他們自己的線程中嗎?我應該將GUI活動(標籤更新)放在他們自己的線程中,以便它們與JButton單擊事件分開進行嗎?

回答

0

對於您來說,瞭解如何執行此操作以及如果您使用NetBeans或有權訪問NetBeans,請參閱默認的Java Desktop Application template。它創建了一個預先連線的桌面應用程序,並在狀態欄中內置了進度欄,當任何「Action」代碼執行時它會自動更新。它利用了Action API,它也被預先連線在後臺線程中運行。

通過查看自動生成的代碼,您將能夠正確並輕鬆地在自己的代碼中實施它。

3

是的,你應該把你的時間激烈閱讀到一個單獨的線程。現在,您在事件分派線程(EDT)中執行所有操作,它將更新您的GUI,但正在忙於讀取數據。

您可以使用SwingWorker。看看Using a Swing Worker Thread看起來像你所需要的。

4

我會說:是的,你的想法將大文件的讀取卸載到單獨的線程是正確的。您不應該在事件調度線程上執行長時間任務,因爲在該線程繁忙時,GUI將無響應,並且您的應用程序會感覺很慢。

這聽起來像SwingWorker的好例子。此類允許您在單獨的線程上執行緩慢的請求(例如磁盤或網絡訪問),並使用EDT將進度更新反饋給GUI。 SwingWorker關注線程之間切換的所有複雜性。您所要做的就是在適當的地方實施您的業務邏輯。太陽有a tutorial on SwingWorker

相關問題