淺談SwingWorker的使用
JDK1.6以后,Swing提供了一個專門的類SwingWorker能幫你解決這個編程范式,你所需要做的就是繼承這個類,重載doInBackground,然后在actionPeformed中調用它的execute方法,并通過publish/process方法來更新界面。
SwingWorker實際上不過是封裝了前面我所說的例子中的MyQueryTask,并做了更詳盡的考慮。execute方法相當于MyQueryTask線程start,它啟動這個后臺線程并立刻返回。SwingWorker 可以注冊PropertyChangeListener,這些listener都被在事件調度線程上執(zhí)行,相當于MyQueryTask中的那些訪問組件的Runnable對象。另外,publish、setProgress只不過是特殊的property事件吧,process和done不過是響應 publish和PropertyChangeEvent.DONE這個事件的方法罷了。因此我們很容易將上面的例子改成SwingWorker的版本:
- voidmyButton_actionPerformed(ActionEventevt){
- newMyQueryTask().execute();
- }
- publicclassMyQueryTaskextendsSwingWorker{
- publicvoiddoInBackground(){
- //查詢數(shù)據(jù)庫
- finalResultSetresult=...;
- //顯示記錄
- for(;result.next();){
- //往表的Model中添加一行數(shù)據(jù),并更新進度條,注意這都是訪問組件
- publish(result);
- }
- ....
- }
- publicvoidprocess(Object...result){
- //往表格中添加數(shù)據(jù)
- jTable.add....
- //更新進度條
- jProgress.setValue(....);
- }
- }
對于一般的耗時任務這樣做是比較普遍的,但是有一些任務是一旦觸發(fā)之后,會周期性的觸發(fā),如何做處理這種任務呢?JDK中提供了兩個Timer類幫你完成定時任務,一個是javax.swing.Timer,一個java.util.Timer。使用它們的方法很簡單,對于Swing的timer,使用方法如下:
- publicvoidmyActionPerformed(){
- //假設點擊了某個按鈕開始記時
- ActionmyAction=newAbstractAction(){
- publicvoidactionPerformed(ActionEvente){
- //做周期性的活動,比如顯示當前時間
- Datedate=newDate();
- jMyDate.setDate(date);//jMyDate是個假想的組件,能顯示日期時間
- }
- };
- newTimer(1000,myAction).start();
- }
java.util.Timer類似,只不過使用TimerTask完成動作封裝。注意這兩個Timer有一個關鍵的區(qū)別:Swing的Timer的事件處理都是在事件調度線程上進行的,因而它里面的操作可以直接訪問Swing組件。而java.util.Timer則可能在其他線程上,因而訪問組件時要使用SwingUtilities.invokeLater和invokeAndWait來進行。這一點要記住。
如果要了解更詳細的信息,可以查閱SwingWorker、Swing Timer和util Timer這些類javadoc文檔和其他網上資料。最重要的是要記住了那兩條原則。
【編輯推薦】