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