アクション


プロパティとイベント

アクションは、Swing においてオブジェクトのプロパティを表現するための
非常に有効な手段であり、しかも、プロパティの変更とイベントを関連付けます

アクションは、まず javax.swing.Action インターフェイスで始まります
このインターフェイスは、アクションに必要な基本的挙動と定数を宣言しています

public interface Action extends ActionListener

アクションは、プロパティ名と値(Object 型)が関連付けられて保存されます
プロパティの設定は Action.putValue() メソッドで行われ
プロパティの取得は Action.getValue() メソッドが使われます

public void putValue(String key , Object value)
public Object getValue(String key)

key には値に関連付けられたキーを示す文字列を指定します
value は、指定したキーに関連付けられたプロパティ値を指定します
通常、キーはクラスやインタフェイスが責任をもって文字列定数を提供します

Microsoft が提唱した C# 言語などは、言語仕様レベルでプロパティという概念があります
Java はプロパティという概念はクラスに存在しませんが
この Action の構造は、純粋なオブジェクト指向として、理想的な形を持っています
プロパティの仕組みを、クラス化することで、プラグイン可能になるからです

Action インターフェイスの実装は javax.swing.AbstractAction クラスです
このクラスは、Action の基本機能を実装し、拡張をサポートしてくれます
public abstract class AbstractAction extends Object
	implements Action, Cloneable, Serializable
このクラスのコンストラクタは次のようになっています

public AbstractAction()
public AbstractAction(String name)
public AbstractAction(String name , Icon icon)

name にはコンポーネントの説明文字列を
icon にはコンポーネントに関連付けるアイコンを指定します
これは、JLabel や JButton で表示されるテキストとアイコンを表しています

また、AbstractAction を拡張する時は
ActionListener.actionPerformed() メソッドを実装することを忘れないで下さい
設計から考えれば、AbstractAction クラスで空実装するべきだったと思うのですが
Swing 開発者はそれを行わなかったため、これを実装する必要があります
このメソッドは、コンポーネントで ActionEvent が発生すると、呼び出されます
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JApplet {
	public void init() {
		Icon icon = new ImageIcon("icon1.jpg");
		Action action = new ButtonAction("Kitty" , icon);
		JButton button = new JButton(action);

		getContentPane().add(button);
	}
	class ButtonAction extends AbstractAction {
		public ButtonAction(String text) {
			super(text);
		}
		public ButtonAction(String text , Icon icon) {
			super(text , icon);
		}
		public void actionPerformed(ActionEvent e) {
			System.out.println("On Action Event");
		}
	}
}
JButton() コンストラクタは、Action をパラメータとして受け取ることができました
JButton は与えられた Action から、プロパティを取得してインスタンスを生成します

このプログラムの ButtonAction クラスは AbstractAction を実装しています
と言っても、actionPerformed() を定義するだけが目的で、それ以外は変わりません

Action インターフェイスは、基本的なプロパティを定数で宣言しています
以下は、Action インターフェイスで定義されているキー用の定数です

フィールト定数解説
ACCELERATOR_KEY アクセラレータとして使用する KeyStroke の格納に使用するキーです
ACTION_COMMAND_KEY JComponent に関連付けられた Keymap に常駐している結果として
Action が通知されるときに生成される
ActionEvent のコマンド文字列の判定に使用するキーです
DEFAULT オブジェクトのプロパティ
(テキストまたはアイコン) を設定または取得するときに
記憶取得キーとして使うと便利な定数です
LONG_DESCRIPTION 詳細な説明を格納するために使われるキーです
MNEMONIC_KEY ニーモニックとして使用する整数値キーコードの格納に使用するキーです
NAME 名前を格納するために使われるキーです
SHORT_DESCRIPTION 短い説明を格納するために使われるキーです。
SMALL_ICON 小さいアイコンを格納するために使われるキーです。

これらの定数を使えば、Swing コンポーネントが必要とする一般的なプロパティを
Action を使って設定することができるようになります
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JApplet {
	public void init() {
		Icon icon = new ImageIcon("icon1.jpg");

		Action action = new ButtonAction();
		action.putValue(Action.NAME , "Kitty on your lap");
		action.putValue(Action.SMALL_ICON , icon);

		JButton button = new JButton(action);
		getContentPane().add(button);
	}
	class ButtonAction extends AbstractAction {
		public void actionPerformed(ActionEvent e) {
			System.out.println("On Action Event");
		}
	}
}
このプログラムは、putValue() メソッドを使ってテキストとアイコンを設定しています
実行結果は、上のプログラムとまったく同じです

さらに重要なのは、プロパティは変更に応じてプログラムが応答する必要があります
多くの場合、プロパティを変更すると、コンポーネントの概観に影響を与えます
そのため、コンポーネントは適切な処理を施し、再描画する必要があります

そこで、Action.addPropertyChangeListener() メソッドを用意しています
このメソッドで登録したリスナは、プロパティが変更されると呼び出されます
登録したりリスナは Action.removePropertyChangeListener() で解除します

public void addPropertyChangeListener(PropertyChangeListener listener)
public void removePropertyChangeListener(PropertyChangeListener listener)

listener には、登録及び解除するリスナを指定します
リスナには java.beans.PropertyChangeListener インターフェイスを指定します

public interface PropertyChangeListener extends EventListener

このインターフェイスには、次のメソッドが宣言されています

public void propertyChange(PropertyChangeEvent evt)

このメソッドは、バウンドプロパティが変更された時に呼び出されます
evt には、イベント発生元と変更したプロパティの情報を持つ
PropertyChangeEvent オブジェクトを指定します

java.beans.PropertyChangeEvent クラスは
変更されたプロパティの情報を格納するイベントクラスです
java.lang.Object
  |
  +--java.util.EventObject
        |
        +--java.beans.PropertyChangeEvent

public class PropertyChangeEvent extends EventObject
このクラスのコンストラクタは、次のようなものが公開されています
public PropertyChangeEvent(
	Object source , String propertyName ,
	Object oldValue , Object newValue
)
source にはイベント発生元を、propertyName にはプロパティのキーを
oldValue は変更前の値、newValue は変更後の値を指定します

変更前の値は PropertyChangeEvent.getOldValue() メソッドで
変更後の値は PropertyChangeEvent.getNewValue() で取得できます

public Object getOldValue()
public Object getNewValue()

これらの機能を使えば、プロパティ変更のタイミングを監視することができます
これは、コンポーネント開発において非常に重要な機能です
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;

public class Test extends JApplet implements PropertyChangeListener {
	public void init() {
		Icon icon = new ImageIcon("icon1.jpg");
		Action action = new ButtonAction();
		action.putValue(Action.NAME , "Kitty on your lap");
		action.putValue(Action.SMALL_ICON , icon);
		action.addPropertyChangeListener(this);
		JButton button = new JButton(action);

		getContentPane().add(button);
	}
	public void propertyChange(PropertyChangeEvent evt) {
		System.out.println("OnPropertyChange");
		System.out.println("Old Value = " + evt.getOldValue());
		System.out.println("New Value = " + evt.getNewValue());
	}

	class ButtonAction extends AbstractAction {
		public void actionPerformed(ActionEvent e) {
			Action action = ((JButton)e.getSource()).getAction();
			action.putValue(Action.NAME , "Tokyo mew mew");
		}
	}
}
このプログラムは、ボタンを押すと、ボタンから Action を取り出し
putValue() メソッドを用いてプロパティの変更を試みます
putValue() が呼び出され、プロパティが変更されると
リスナの propertyChange() メソッドが呼び出されることを確認することができるでしょう

ボタンの Action は AbstractButton.getAction() で得ることができます
このプログラムでは ButtonAction.actionPerformed() メソッド内で使っています

public Action getAction()

このメソッドは、ボタンに設定されている Action を返します



前のページへ戻る次のページへ