通常,当我创建 Swing(或任何 UI)应用程序时,我会在菜单项和按钮上显示各种操作。我通常会创建一个操作注册表并将操作存储在其中,然后当某些事情发生时,我会根据应用程序的状态禁用/启用注册表中的操作。我不会称自己为狂热的 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<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 提醒说,它比简单的观察者要重一些。来自ActionJavaDoc:
请注意,Action 实现在存储方面往往比典型的 ActionListener 更昂贵,后者不提供集中控制功能和广播属性更改的好处。出于这个原因,您应该注意只在需要其好处的地方使用 Action,并在其他地方使用简单的 ActionListener。
我通常采取以下方法:
Action包含Component的操作映射中。String“拉出” (例如,将其添加到 a 、等)。ActionComponentJToolBarJMenuBarupdateActionStates()方法Component,当用户执行某些操作时调用该方法(例如,从 a 中选择 N 行JTable)。此方法根据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));
顺便说一句,我通常更喜欢Actions 而不是ActionListeners 来公开Action构成我Component的 API 一部分的 s。对于仅存在于Component(例如对话框的“清除”按钮)中的操作,我通常使用ActionListener. 但是,我不同意 akfActionListener作为最标准的方法——这可能适用于较小的 GUI,但不适用于更复杂的 Swing 应用程序。
我在动作上使用注释,然后反思性地找到它们。
有点整洁,新的操作会自动管理。