使用注册表管理Swing操作

通常,当我创建Swing(或任何UI)应用程序时,我会在菜单项和按钮上显示各种操作。 我通常创建一个动作注册表并将动作存储在那里,然后当发生某些事情时,我会根据应用程序的状态在注册表中禁用/启用动作。 我不会称自己是一个狂热的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 actionMap = new ImmutableClassToInstanceMap.Builder(). 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 actionClasss) { return actionMap.getInstance(actionClasss); } } 

现在禁用,说ZoomAction,我用

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

根据我的经验,处理在Swing GUI上执行的操作的“ ”标准方法是创建ActionListener并让它们直接为它们注册的组件处理ActionEvent 。 它是一个简单的设计,它遵循Swing框架中的其他种类GUI事件( MouseListener / MouseEventTableModelListener / TableModelEvent等)的约定。

您描述的Action框架是一个强大的工具,允许在许多输入方法之间共享操作(即,使工具栏按钮和菜单项执行相同的操作,因此共享相同的Object以处理由两者触发的事件等。 )。 这种抽象很酷,但Sun提醒说它比简单的Observers重一点。 来自Action JavaDoc:

请注意,Action的实现在存储方面往往比典型的ActionListener更昂贵,后者不提供集中控制function和广播属性更改的好处。 出于这个原因,您应该注意只使用需要其好处的Actions,并在其他地方使用简单的ActionListener。

我通常采取以下方法:

  • 使用包含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来暴露构成我的Component API的一部分的Action 。 对于仅存在于Component Actions(例如对话框的“Clear”按钮),我通常使用ActionListener 。 但是,我不同意akf关于ActionListener是最标准的方法 – 这可能适用于较小的GUI但不是更复杂的Swing应用程序。

我在动作上使用注释,然后反思地找到它们。

有点整洁,新的操作会自动管理。