通常,當我創建Swing(或任何UI)應用程序時,我會在菜單項和按鈕上出現各種操作。我通常會創建一個操作註冊表並將操作存儲在那裏,然後當某些事情發生時,我會根據應用程序的狀態禁用/啓用註冊表中的操作。 我不會稱自己是一個狂熱的Swing開發人員,儘管我知道自己的方式足夠好,但這是管理Actions的典型模式嗎?還是有更標準的做法呢?使用註冊表管理Swing操作
感謝,
傑夫
通常,當我創建Swing(或任何UI)應用程序時,我會在菜單項和按鈕上出現各種操作。我通常會創建一個操作註冊表並將操作存儲在那裏,然後當某些事情發生時,我會根據應用程序的狀態禁用/啓用註冊表中的操作。 我不會稱自己是一個狂熱的Swing開發人員,儘管我知道自己的方式足夠好,但這是管理Actions的典型模式嗎?還是有更標準的做法呢?使用註冊表管理Swing操作
感謝,
傑夫
傑夫,你的方法似乎是一個很好的方法。我做同樣的事情。我所說的註冊表的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);
從我的經驗,處理的Swing GUI執行的操作「最」的標準方法是創建ActionListener
S和讓他們直接處理ActionEvent
S爲組件與他們登記。這是一個簡單的設計,它遵循Swing框架中其他種類的GUI事件的約定(MouseListener
/MouseEvent
,TableModelListener
/TableModelEvent
等)。
的Action
框架你的描述是一個強大的工具,允許多種輸入法之間的行動(共享即,具有工具欄按鈕和菜單項執行相同的操作,因此共享相同Object
用於處理由觸發的事件兩者等)。這種抽象非常酷,但是Sun提醒說它比簡單的觀察者稍重一些。從Action
JavaDoc:
注意動作的實現往往在存儲比典型的ActionListener,它不提供的功能和屬性更改廣播的集中控制的好處而言更加昂貴。出於這個原因,您應該注意只在需要其好處的地方使用Actions,並在其他地方使用簡單的ActionListener。
我通常採取如下方法:
Component
的動作映射註冊Action
。String
常數允許應用自舉代碼從Component
在要求的「拉出」該Action
(例如將它添加到一個JToolBar
,JMenuBar
等)。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應用程序。
我使用的行動註解,然後若有所思地找到它們。
有點整潔,並採取新的行動得到自動管理。
這一切都是有道理的,這通常是我採取的方法。我想我只是試圖找到最好的方式來管理行動,當我需要使用它們... –