8

通常、Swing (または任意の UI) アプリケーションを作成するとき、メニュー項目とボタンに表示されるさまざまなアクションがあります。私は通常、アクション レジストリを作成してそこにアクションを保存し、特定のことが発生すると、アプリケーションの状態に基づいてレジストリ内のアクションを無効/有効にします。私は自分自身を熱心な Swing 開発者とは呼びませんが、それを回避する方法は十分に知っていますが、これはアクションを管理するためのかなり典型的なパターンですか? それとももっと標準的な方法がありますか?

ありがとう、

ジェフ

4

4 に答える 4

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);
于 2009-08-25T07:53:50.273 に答える
5

私は通常、次のアプローチを取ります。

  • Actionを含むComponentのアクション マップに登録します。
  • アプリケーションのブートストラップ コードが必要なからStringを「引き出す」ことができるようにする public 定数を定義します (たとえば、 、 などに追加します)。ActionComponentJToolBarJMenuBar
  • 内にプライベートupdateActionStates()メソッドを定義しますComponent。これは、ユーザーがアクションを実行したときに呼び出されます (たとえば、 から 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));

ちなみに、私は通常、の API の一部を形成する を公開するためActionに、 よりも を好みます。(ダイアログの「クリア」ボタンなど)内にのみ存在するアクションの場合、通常は を使用します。ただし、最も標準的なアプローチであるという akf には同意しません。これは、小規模な GUI には当てはまりますが、より複雑な Swing アプリケーションには当てはまりません。ActionListenerActionComponentComponentActionListenerActionListener

于 2009-08-25T07:52:03.553 に答える
5

私の経験から、Swing GUI で実行されるアクションを処理する「最も」標準的な方法は、 を作成し、それらが登録されているコンポーネントの を直接ActionListener処理することです。ActionEventこれは単純な設計であり、Swing フレームワークの他の種類の GUI イベント ( MouseListener/ MouseEventTableModelListener/TableModelEventなど) の規則に従います。

あなたが説明するフレームワークは、多くの入力方法間でアクションを共有できる強力なツールです (つまり、ツールバー ボタンとメニュー項目が同じアクションを実行するため、両方によってトリガーされるイベントを処理するActionために同じアクションを共有するなど)。Objectこの抽象化は非常に優れていますが、Sun は単純な Observer よりも重みが少し重いと警告しています。JavaDocから:Action

Action の実装は、一般的な ActionListener よりもストレージの点で高価になる傾向があることに注意してください。これは、機能の集中管理とプロパティ変更のブロードキャストの利点を提供しません。このため、利点が必要な場合にのみ Action を使用し、他の場所では単純な ActionListener を使用するように注意する必要があります。

于 2009-08-25T00:45:49.843 に答える
0

私はアクションに注釈を使用しており、反射的にそれらを見つけています。

少し整理され、新しいアクションが自動的に管理されます。

于 2011-03-07T02:49:26.047 に答える