2009-08-24 95 views
8

通常,當我創建Swing(或任何UI)應用程序時,我會在菜單項和按鈕上出現各種操作。我通常會創建一個操作註冊表並將操作存儲在那裏,然後當某些事情發生時,我會根據應用程序的狀態禁用/啓用註冊表中的操作。 我不會稱自己是一個狂熱的Swing開發人員,儘管我知道自己的方式足夠好,但這是管理Actions的典型模式嗎?還是有更標準的做法呢?使用註冊表管理Swing操作

感謝,

傑夫

回答

10

傑夫,你的方法似乎是一個很好的方法。我做同樣的事情。我所說的註冊表的ActionHandler,它看起來像這樣:

import com.google.common.collect.ClassToInstanceMap; 
import com.google.common.collect.ImmutableClassToInstanceMap; 

import javax.swing.*; 
import javax.swing.text.DefaultEditorKit; 

public class ActionHandler { 

    private static final ClassToInstanceMap<Action> actionMap = 
      new ImmutableClassToInstanceMap.Builder<Action>(). 
        put(DefaultEditorKit.CutAction.class, new DefaultEditorKit.CutAction()). 
        put(DefaultEditorKit.CopyAction.class, new DefaultEditorKit.CopyAction()). 
        put(DefaultEditorKit.PasteAction.class, new DefaultEditorKit.PasteAction()). 
        put(RefreshAction.class, new RefreshAction()). 
        put(MinimizeAction.class, new MinimizeAction()). 
        put(ZoomAction.class, new ZoomAction()). 
        build(); 

    public static Action getActionFor(Class<? extends Action> actionClasss) { 
     return actionMap.getInstance(actionClasss); 
    } 
} 

現在禁用,說ZoomAction,我用

ActionHandler.getActionFor(ZoomAction.class).setEnabled(false); 
5

從我的經驗,處理的Swing GUI執行的操作「」的標準方法是創建ActionListener S和讓他們直接處理ActionEvent S爲組件與他們登記。這是一個簡單的設計,它遵循Swing框架中其他種類的GUI事件的約定(MouseListener/MouseEvent,TableModelListener/TableModelEvent等)。

Action框架你的描述是一個強大的工具,允許多種輸入法之間的行動(共享即,具有工具欄按鈕和菜單項執行相同的操作,因此共享相同Object用於處理由觸發的事件兩者等)。這種抽象非常酷,但是Sun提醒說它比簡單的觀察者稍重一些。從Action JavaDoc:

注意動作的實現往往在存儲比典型的ActionListener,它不提供的功能和屬性更改廣播的集中控制的好處而言更加昂貴。出於這個原因,您應該注意只在需要其好處的地方使用Actions,並在其他地方使用簡單的ActionListener。

+0

這一切都是有道理的,這通常是我採取的方法。我想我只是試圖找到最好的方式來管理行動,當我需要使用它們... –

5

我通常採取如下方法:

  • 與含Component的動作映射註冊Action
  • 定義一個公共String常數允許應用自舉代碼從Component在要求的「拉出」該Action(例如將它添加到一個JToolBarJMenuBar等)。
  • 定義Component中的私人updateActionStates()方法,當用戶執行某些操作(例如,從JTable中選擇N行)時調用該方法。此方法根據Component的當前狀態啓用/禁用所有定製操作。

實施例:

public class MyPanel extends JPanel { 
    public static final String MY_ACTION_NAME = "MyAction"; 

    private final JTable myTable;  

    public MyPanel() { 
    // Create action and define behaviour. 
    this.myAction = new AbstractAction(MY_ACTION_NAME, ...); 

    // Register with component's action map. 
    getActionMap().put(myAction.getValue(Action.NAME), myAction); 

    // Optionally register keyboard shortcuts using component's input map. 
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(...); 

    // Create JTable and add a call to updateActionStates when the selection changes. 
    myTable = new JTable(...); 
    myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { 
     public void valueChanged(ListSelectionEvent evt) { 
     updateActionStates(); 
     } 
    }); 
    } 

    private void updateActionStates() { 
    // Action will only be enabled if one table row is selected. 
    getActionMap.get(MY_ACTION_NAME).setEnabled(myTable.getSelectedRowCount == 1); 
    } 
} 

// Application start-up code: 

MyPanel pnl = new MyPanel(); 
JToolBar toolBar = new JToolBar(); 
// Pull out action from action map and add to toolbar. 
toolBar.add(pnl.getActionMap().get(MyPanel.MY_ACTION_NAME)); 

順便提及,我通常偏好Action s至ActionListener S代表暴露Action s表示形成我Component的API的一部分。對於僅存在於Component內的操作(​​例如對話框的「清除」按鈕),我通常使用ActionListener。但是,我不同意akf關於ActionListener是最標準的方法 - 這可能適用於較小的GUI,但不適用於更復雜的Swing應用程序。

0

我使用的行動註解,然後若有所思地找到它們。

有點整潔,並採取新的行動得到自動管理。