JTextFieldやJTextAreaなどにコピーや貼り付けなどのポップアップメニューを追加する。
SwingのJTextFieldなどは、デフォルトではポップアップメニューが現れません。
ポップアップメニューは大半の場合は、コピー、貼り付けなどのメニューで
十分ですが、場合によってはそれ以外のメニューを扱いたい場合もあります。
Swingは汎用的に作られているので、設定されていないのでしょう。
でも、コピーや貼り付けぐらいは欲しいです。
JTextFieldなどのコンポーネントにはそれらのActionが最初から用意されているので、それらを使えば簡単に実装できます。
ただ、日本語ではないので、その辺の指定はしてやる必要があります。
以下のソースは JTextField, JTextArea, JPasswordFieldに対して使えます。
ポップアップメニューに表示されるメニューは、切り取り、コピー、貼り付け、す
べて選択、の4つです。
編集不可の場合(editable=false)は、切り取り、貼り付けがグレイになります。
パスワードの場合は切り取り、コピーはメニューに現れません。
package verticalviewer.util; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.JMenuItem; import javax.swing.JPasswordField; import javax.swing.JPopupMenu; import javax.swing.text.JTextComponent; /** * Swing拡張クラス. * 国際化対応していない。 */ public class SwingX { /** * ポップアップメニューにメニューを追加します. * 別のメニューを追加したい場合はこのメソッドを使います。 * デフォルトのメニューのみでよいのであれば、addPopupMenu(JTextComponent)が便利です。 */ public static void addMenuItems(JTextComponent comp, JPopupMenu popup) { assert comp != null; assert popup != null; ActionMap map = comp.getActionMap(); boolean isEditable = comp.isEditable(); if (comp instanceof JPasswordField) { popup.add(createMenuItem(map.get("paste-from-clipboard"), "貼り付け(P)", KeyEvent.VK_P, isEditable)); popup.addSeparator(); popup.add(createMenuItem(map.get("select-all"), "すべて選択(A)", KeyEvent.VK_A, true)); } else { popup.add(createMenuItem(map.get("cut-to-clipboard"), "切り取り(T)", KeyEvent.VK_T, isEditable)); popup.add(createMenuItem(map.get("copy-to-clipboard"), "コピー(C)", KeyEvent.VK_C, true)); popup.add(createMenuItem(map.get("paste-from-clipboard"), "貼り付け(P)", KeyEvent.VK_P, isEditable)); popup.addSeparator(); popup.add(createMenuItem(map.get("select-all"), "すべて選択(A)", KeyEvent.VK_A, true)); } } private static JMenuItem createMenuItem(Action action, String text, int mnemonic, boolean enable) { JMenuItem menu = new JMenuItem(action); menu.setText(text); menu.setMnemonic(mnemonic); menu.setEnabled(enable); return menu; } /** * コンポーネントに対してデフォルトのポップアップメニューを表示させるようにする. * マウスリスナーを追加し、その中でポップアップメニューを表示する処理を行っています。 * デフォルト以外のメニューを追加したい場合は、addMenuItems(JTextComponent, JPopupMenu)を * 使ってください。 * */ public static void addPopupMenuMouseListener(JTextComponent comp) { assert comp != null; comp.addMouseListener(new TextComponentMouseListener(comp)); } static class TextComponentMouseListener extends MouseAdapter { final JTextComponent comp; TextComponentMouseListener(JTextComponent comp) { this.comp = comp; } public void mouseReleased(MouseEvent ev) { if (ev.isPopupTrigger()) { JPopupMenu popup = new JPopupMenu(); addMenuItems(comp, popup); popup.show(comp, ev.getX(), ev.getY()); } } } }
使い方はこんな感じです。
JTextField name = new JTextField("新規作成"); SwingX.addPopupMenuMouseListener(name); getContentPane().add(name);
(2006/11/21追記)あれっ?動かないかも???
(2006/11/24追記)
以前のソースだと、cut,copy,pasteが動きませんでした。select-allだけは動きました。
なぜか、cut,copy,pasteは同じ機能と思われるActionがもう一組登録されています。
名前は、"cut-to-clipboard","copy-to-clipboard","paste-from-clipboard"です。
こちらのActionを使うようにするといけました。
Swingのソースを詳しく見ていないけど、ActionEventのsourceがJTextComponentではなく、JPopupMenuになってしまうので、それで処理がうまく実行されない、っぽいです。