8


6

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

ありがとう、

ジェフ

4 Answer


10


ジェフ、あなたのアプローチは良いアプローチのようです。 私も同じことをします。 私はレジストリをActionHandlerと呼び、それはこのように見えます:

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

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

パブリッククラスActionHandler {

プライベートstatic final ClassToInstanceMap actionMap = new ImmutableClassToInstanceMap.Builder()。 put(DefaultEditorKit.CutAction.class、新しいDefaultEditorKit.CutAction()) put(DefaultEditorKit.CopyAction.class、新しいDefaultEditorKit.CopyAction())。 put(DefaultEditorKit.PasteAction.class、新しいDefaultEditorKit.PasteAction())。 put(RefreshAction.class、新しいRefreshAction())。 put(MinimizeAction.class、新しいMinimizeAction())。 (ZoomAction.class、新しいZoomAction())を追加します。 build();

public static Action getActionFor(Class <? Action> actionClasssを継承します。{return actionMap.getInstance(actionClasss);} }}

無効にするには、ZoomActionと言います。

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


5


私の経験上、Swing GUI上で実行されるアクションを扱うための 'most'標準的な方法は ActionListener`を作成し、それらが登録されているコンポーネントのために ActionEvent`を直接扱うことです。 これは単純な設計であり、Swingフレームワークの他の種類のGUIイベント( MouseListener /` MouseEvent`、 TableModelListener /` TableModelEvent`など)との規約に従います。

あなたが記述する Action`フレームワークは多くのインプットメソッド間でアクションを共有することを可能にする強力なツールです。両方など)。 この抽象概念はかなりクールですが、Sunは単純なObserversよりも少し重いことを注意してください。 http://java.sun.com/javase/6/docs/api/javax/swing/Action.html [`Action JavaDoc:]から

_ アクションの実装は、機能の集中制御とプロパティ変更のブロードキャストの利点を提供しない典型的なActionListenerよりもストレージの点で高価になる傾向があることに注意してください。 このため、メリットが必要な場合にのみアクションを使用し、他の場所では単純なActionListenerを使用するように注意する必要があります。 _


5


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

  • それを含む Component`のアクションマップで Action`を登録してください。

  • アプリケーションのブートストラップコードが必要に応じて Component`から Action`を「引き出す」ことを可能にするpublicの String`定数を定義します。 それを `JToolBar`や JMenuBar`などに追加します。

  • Component`内にプライベートな updateActionStates() `メソッドを定義します。これはユーザーが何らかのアクションを実行したときに呼び出されます(例: JTableからN行を選択します。 このメソッドは `Component`の現在の状態に基づいてすべてのオーダーメイドのアクションを有効/無効にします。

例:

パブリッククラスMyPanelはJPanelを継承します。{public static final String MY_ACTION_NAME = "MyAction";

プライベートファイナルJTable myTable。

public MyPanel(){//アクションを作成し、動作を定義します。 this.myAction = new AbstractAction(MY_ACTION_NAME、...);

//コンポーネントのアクションマップに登録する getActionMap()。put(myAction.getValue(Action.NAME)、myAction);

//必要に応じて、コンポーネントの入力マップを使用してキーボードショートカットを登録します。 getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(...);

// JTableを作成し、選択が変更されたときにupdateActionStatesへの呼び出しを追加します。 myTable = new JTable(...); myTable.getSelectionModel()。addListSelectionListener(new ListSelectionListener(){public void valueChanged(ListSelectionEvent evt){updateActionStates();}}); }

private void updateActionStates(){// 1つのテーブル行が選択されている場合にのみアクションが有効になります。 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));

ちなみに、私は通常、私の Component`のAPIの一部を形成する Action`を公開するために Action`を ActionListener`よりも好みます。 単に `Component`内に存在するアクション(例えば ダイアログの「クリア」ボタン)私は通常 `ActionListener`を使います。 しかし、私はakfが `ActionListener`が最も標準的なアプローチであることに反対しています - これはより小さなGUIには当てはまりますが、より複雑なSwingアプリケーションには当てはまりません。


0


私はアクションにアノテーションを使っていて、それからそれを反射的に見つけます。

少々手間がかかり、新しいアクションが自動的に管理されます。