Actionクラスで一括管理
ActionListenerとAbstactAction
メニューアイテムやボタン等の設定方法として、一番よく知られているのはActionListenerを実装することかもしれません。
しかし、メニューアイテムやボタンにActionListener、テキスト、ツールチップ等を設定して、それらをメニュー、ツールバー、ポップアップメニューに追加していく作業は非常に面倒なものです。そこで、AbstractActionを継承したクラスを使って、これらの設定をまとめてやってしまう方法を紹介しましょう。
Actionクラスという概念はJavaには有りませんが、今回参考にさせていただいた『Java GUIプログラミング〈Vol.1〉さらにパワーアップしたSwing』(大村 忠史 著)にならって、AbstractActionを継承しているクラス(それゆえにActionインターフェースを実装するクラス)を便宜上「Actionクラス」と呼ばせてもらいます。
メニュー、ツールバー、ポップアップメニューをまとめて管理する
今回はテキストエディタのようなものを作ってみます。といってもコピー、ペーストの機能だけを持つ簡単なものです。
ActionTest.java
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ActionTest extends JFrame { JTextArea textArea; AbstractAction copyAction; AbstractAction pasteAction; JPopupMenu popupMenu; public static void main(String[] args){ ActionTest f=new ActionTest("Actionクラスで一括管理"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(400,300); f.setVisible(true); } public ActionTest(String title){ super(title); //Actionクラスの初期化 copyAction=new CopyAction(); pasteAction=new PasteAction(); //コンポーネントの生成 JPanel panel=(JPanel)getContentPane(); //テキストエリア textArea=new JTextArea(); textArea.addMouseListener(new CheckPopup()); panel.add(textArea, BorderLayout.CENTER); //メニューバー JMenuBar menuBar=new JMenuBar(); setJMenuBar(menuBar); //編集メニュー JMenu editMenu=new JMenu("編集"); menuBar.add(editMenu); editMenu.add(copyAction); editMenu.add(pasteAction); //モードメニュー JMenu modeMenu=new JMenu("モード"); menuBar.add(modeMenu); ButtonGroup bg=new ButtonGroup(); JRadioButtonMenuItem editableMI=new JRadioButtonMenuItem("編集可"); editableMI.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ pasteAction.setEnabled(true);//貼付け可 textArea.setEditable(true); } }); modeMenu.add(editableMI); bg.add(editableMI); JRadioButtonMenuItem uneditableMI=new JRadioButtonMenuItem("編集不可"); uneditableMI.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ pasteAction.setEnabled(false);//貼付け不可 textArea.setEditable(false); } }); modeMenu.add(uneditableMI); bg.add(uneditableMI); editableMI.setSelected(true); //ツールバー JToolBar toolBar=new JToolBar(); panel.add(toolBar, BorderLayout.NORTH); toolBar.add(copyAction); toolBar.add(pasteAction); //ポップアップメニュー popupMenu=new JPopupMenu(); popupMenu.add(copyAction); popupMenu.add(pasteAction); } //ポップアップメニューの表示用 class CheckPopup extends MouseAdapter { public void mousePressed(MouseEvent e){ if(SwingUtilities.isRightMouseButton(e)){ popupMenu.show(e.getComponent(), e.getX(), e.getY()); } } } /*CopyActionだけでメニュー、ツールバー、ポップアップメニュー すべてのコピー機能とGUIを実装*/ class CopyAction extends AbstractAction { CopyAction(){ putValue(Action.SMALL_ICON, new ImageIcon("Copy24.gif")); putValue(Action.NAME, "コピー"); putValue(Action.SHORT_DESCRIPTION, "コピー"); } public void actionPerformed(ActionEvent e){ textArea.copy(); } } /*PasteActionだけでメニュー、ツールバー、ポップアップメニュー すべてのペースト機能とGUIを実装*/ class PasteAction extends AbstractAction { PasteAction(){ putValue(Action.SMALL_ICON, new ImageIcon("Paste24.gif")); putValue(Action.NAME, "貼付け"); putValue(Action.SHORT_DESCRIPTION, "貼付け"); } public void actionPerformed(ActionEvent e){ textArea.paste(); } } }
![]() |
![]() |
実行してみましょう。
最初のスクリーンショットは、ポップアップメニューから文字列の貼付けをしようとしているところです。予め「Javaで楽しく」がコピーされている状態です。

さあ、どうなるでしょうか。

できました。
メニュー、ツールバー、ポップアップメニューのいずれからでも、コピーとペーストが実行できます。
次の部分に注目してください。CopyAction、PasteActionが今回の主役Actionクラスです。
この部分だけで、メニューアイテム、ツールバーのボタン、ポップアップメニューアイテムのアイコン、テキスト、ツールチップ、機能がまとめて設定されているのです。これらActionクラスのインスタンスをメニューなどに追加するだけでGUIが完成します。
/*CopyActionだけでメニュー、ツールバー、ポップアップメニュー すべてのコピー機能とGUIを実装*/ class CopyAction extends AbstractAction { CopyAction(){ putValue(Action.SMALL_ICON, new ImageIcon("Copy24.gif")); putValue(Action.NAME, "コピー"); putValue(Action.SHORT_DESCRIPTION, "コピー"); } public void actionPerformed(ActionEvent e){ textArea.copy(); } } /*PasteActionだけでメニュー、ツールバー、ポップアップメニュー すべてのペースト機能とGUIを実装*/ class PasteAction extends AbstractAction { PasteAction(){ putValue(Action.SMALL_ICON, new ImageIcon("Paste24.gif")); putValue(Action.NAME, "貼付け"); putValue(Action.SHORT_DESCRIPTION, "貼付け"); } public void actionPerformed(ActionEvent e){ textArea.paste(); } }
さらに次の部分にも注目してください。
//編集メニュー ... editMenu.add(copyAction); editMenu.add(pasteAction); ... //ツールバー ... toolBar.add(copyAction); toolBar.add(pasteAction); //ポップアップメニュー ... popupMenu.add(copyAction); popupMenu.add(pasteAction);
JMenuItemインスタンスやJButtonインスタンスを生成してから追加しているのではなくて、Actionクラスのインスタンスをそのまま追加しているところがミソです。とても楽ですね。
メリットはまだ有ります。

モードメニューから編集不可を選ぶと、

メニュー、ツールバー、ポップアップメニューのすべてにおいて、貼付けができなくなりました。実はこれもコード中のただ1カ所だけで設定されています。次の部分です。
pasteAction.setEnabled(false);//貼付け不可
このように、Actionクラスを活用すると、コードが非常に簡潔になります。
また、プログラムのメンテナンスも非常に楽になります。何しろ、メニューアイテムやボタンの外観を変えるのに、Actionクラスの中だけを書き換えればいいのですから。
NetBeansやEclipseで開発する場合でさえも、Actionクラスを使うとメンテナンスが楽になるでしょう。