Swing應用程式架構(Swing Application Framework)API緒論(JSR-296)之二(翻譯)

來源:互聯網
上載者:User
 
用 @Action 標註定義動作

@Action標註打算作為Action的actionPerformed方法。ApplicationContext.getActionMap
方法建立了包含由某些類定義的每個@Action的Action對象的ActionMap。ActionMap將父類連結起來,並且每個
Application的子類都有父類。這樣,所有的應用程式繼承了從Application基類定義的cut,copy,paste,delete和
quit動作。

SingleFrameExample4.java定義了兩個@Actions,open和close:

 

/**
 * Load the specified file into the textPane or popup an error
 * dialog if something goes wrong.  
 */
@Action public void open() {
    JFileChooser chooser = new JFileChooser();
    int option = chooser.showOpenDialog(getMainFrame());
    if (option == JFileChooser.APPROVE_OPTION) {
    File file = chooser.getSelectedFile();
    textPane.setPage(file.toURI().toURL());
    // error handling omitted for clarity
    }
}
/**
 * Replace the contents of the textPane with the value of the
 * "defaultText" resource.  
 */
@Action public void close() {
    ApplicationContext ac = ApplicationContext.getInstance();
    String ac.getResourceMap(getClass()).getString("defaultText");
    textPane.setText(defaultText);
}
 

 

 

使用ApplicationContext的getActionMap方法來建立包含open和close的ActionMap。為了簡化查詢,通過建立一個私人的工具方法來完成,這和上面的查詢app類的ResourceMap相似。

 

private javax.swing.Action getAction(String actionName) {
    ApplicationContext ac = ApplicationContext.getInstance();
    return ac.getActionMap(getClass(), this).get(actionName);
}
/* We use getAction to set the action property of menu items
 * and buttons and so on:
*/
openMenuItem.setAction(getAction("open"));
closeMenuItem.setAction(getAction("close"));
    

 

以這種方法定義的Action的預設表示特性當從類的ResourceBundle載入時初始化。這樣,Action的text,
mnemonic, tooltip (shortDescription), and
shortcut被定義在SingleFrameExample4.properties的ResourceBundle裡:

open.Action.text = &Open...
open.Action.accelerator = control O
open.Action.shortDescription = open a document

close.Action.text = &Close
close.Action.shortDescription = close the document

如果運行,將看見Action及其所有資源。

SingleFrameExample4 螢幕

 

編寫動作可能困難的一個方面是處理那些潛在佔用漫長時間或者阻塞的任務,比如檔案系統或者網路訪問。應用程式必須在後台線程裡完成這些任務,讓
Swing事件指派線程(EDT)不會阻塞。在本例中,由JTextPane類處理非同步檔案載入。在許多情況下,應用程式開發人員必須直接處理在後台上的運
行任務。應用程式架構Task類(基於SwingWorker)簡化了非同步執行的動作的編寫。

產生背景工作的動作

SwingWorker類在後台線程上計算數值,然後在事件指派線程上調用完成方法。應用程式通過覆蓋SwingWorker
done方法,或者增加一個PropertyChangeListener,或者覆蓋process方法,能夠監視SwingWorker並安全重新整理
GUI。它們當後台線程調用publish()方法時收到中間結果。能夠測量它們自己進度的SwingWorker,設定進度特性通知
PropertyChangeListener已經完成工作的百分比。

應用程式架構定義一個叫做Task的SwingWorker的子類,Task加入了一些特性讓後台線程比較容易監視和管理。任務自動初始化從
ResourceBundle載入的描述性特性。@Action方法能夠返回一個Task對象,而架構將執行後台線程的Task。例如,這裡的Task只
是睡眠大約1500毫秒。

class DoNothingTask extends Task {
    @Override protected Void doInBackground() throws InterruptedException {
    for(int i = 0; i < 10; i++) {
        setMessage("Working [" + i + "]");
        Thread.sleep(150L);
        setProgress(i, 0, 9);
    }
    Thread.sleep(150L);
    return null;
    }
    @Override protected void done() {
    setMessage(isCancelled() ? "Canceled." : "Done.");
    }
}

 

儘管DoNothingTask產生一個訊息並周期地更新進度特性,但是大多數情況下它只是睡眠。顯而易見,這類事情不必在事件指派線程上執行。啟動在後台線程上DoNothingTask的@Action可能像這樣編寫:

@Action Task JustDoNothing() {
return new DoNothingTask();
}

 

ActionExample4.java提供了一個孵化Task的@Action的有趣樣本。它使用一個遍曆枚舉目錄裡所有檔案的
Task(ListFileTask),每次發布大約10個檔案。Task使用publish方法將中間結果交付給運行在EDT上的process方法。
ActionExample4.java通過建立一個覆蓋process方法的應用程式的子類使用ListFilesTask來更新GUI:

 

private class DoListFiles extends ListFilesTask {
    public DoListFiles(File root) {  // ctor runs on the EDT
    super(root);
    listModel.clear();
    }
    @Override protected void process(List files) {
    if (!isCancelled()) {
        listModel.addAll(files);
    }
    }
}

private Task doListFiles = null;

@Action 
public Task go() {
    stop();  // stop the pending DoListFiles task (if any)
    setStopEnabled(true);
    File root = new File(rootTextField.getText());
    return new DoListFiles(root);
}

@Action(enabledProperty = "stopEnabled")
public void stop() {
    if ((doListFiles != null) && !doListFiles.isCancelled()) {
    if (doListFiles.cancel(true)) {
        doListFiles = null;
        setStopEnabled(false);
    }
    }
}
    

 

如果運行ActionExample4,將會注意到當應用程式後台正忙於枚舉檔案時,GUI依然保持可響應狀態。本例以
PropertyChangeListener監視由後台Task產生的訊息並在視窗底部將它們顯示出來(這段代碼在上面未列出)。監視背景工作的狀態典
型地由TaskMonitor類處理。SingleFrameExample5使用TaskMonitor類,它是下節的主題。

ActionExample4 螢幕

 

本例也引入了綁定啟用@Action狀態為特性當前特性值的enabledProperty的標註參數。也存在一個指示GUI在背景工作運
行時應當阻塞的block標註參數(示範未體現)。對樣本中@Action(block =
Block.ACTION)意味著當背景工作正運行時Action對象自身應當禁止。為了用模態對話方塊阻塞全部GUI,通過指定block =
lock.APPLICATION來替代。ActionExample5.java示範了所有的可能性。

一個小而全的應用程式

SingleFrameExample5.java是迄今為止提供的最接近完整的應用程式。通過從JPL
photojournal網址上下載某些非常巨大的火星探測器的映像,它打算突出背景工作的重要性。應用程式允許使用者一步一步下載映像,並且搶先或者取消
當前的下載/顯示任務。應用程式的結構是典型的,包括了用將通用任務和應用程式GUI串連的子類(ShowImageTask)特化通用Task類(本例
中的LoadImageTask)。

在前一節描述了Task管理大多數基礎。幾個額外的細節值得在此強調:

  • StatusBar使用共用的TaskMonitor來顯示當前"前台”任務。
  • 通過顯式終止映像讀取操作(如果操作進行中),LoadImageTask需要特別處理取消任務。通過覆蓋Task.done(不是cancel,它是最終結構)方法來處理。
  • 正如@Action所為,通過預設的TaskService執行一個Task的ready()方法,顯示第一幅映像。

SingleFrameExample5螢幕: Mars Rover(火星探測器)的著陸視圖

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.