TITLE:JTableのセルエディタにJPopumMenuを設定
#navi(../)
#tags(JTable, TableCellEditor, UndoManager, JPopumMenu, AncestorListener)
RIGHT:Posted by &author(aterai); at 2010-04-26
*JTableのセルエディタにJPopumMenuを設定 [#be1eecdb]
``JTable``のセルエディタに、``Copy``、``Paste``、``Undo``、``Redo``などを行う``JPopumMenu``を設定します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTIn7Rc6TI/AAAAAAAAATE/drRaDYiUB1w/s800/CellEditorPopupMenu.png)

**サンプルコード [#nb35d2a6]
#code(link){{
public static JPopupMenu installTextComponentPopupMenu(final JTextComponent tc) {
  final UndoManager manager = new UndoManager();
  final Action undoAction   = new UndoAction(manager);
  final Action redoAction   = new RedoAction(manager);
  final Action cutAction    = new DefaultEditorKit.CutAction();
  final Action copyAction   = new DefaultEditorKit.CopyAction();
  final Action pasteAction  = new DefaultEditorKit.PasteAction();
  final Action deleteAction = new AbstractAction("delete") {
    @Override public void actionPerformed(ActionEvent e) {
      JPopupMenu pop = (JPopupMenu)e.getSource();
      ((JTextComponent)pop.getInvoker()).replaceSelection(null);
    }
  };
  tc.addAncestorListener(new AncestorListener() {
    @Override public void ancestorAdded(AncestorEvent e) {
      manager.discardAllEdits();
      tc.requestFocusInWindow();
    }
    @Override public void ancestorMoved(AncestorEvent e) {}
    @Override public void ancestorRemoved(AncestorEvent e) {}
  });
  tc.getDocument().addUndoableEditListener(manager);
  tc.getActionMap().put("undo", undoAction);
  tc.getActionMap().put("redo", redoAction);
  InputMap imap = tc.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK), "undo");
  imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK), "redo");

  JPopupMenu popup = new JPopupMenu();
  popup.add(cutAction);
  popup.add(copyAction);
  popup.add(pasteAction);
  popup.add(deleteAction);
  popup.addSeparator();
  popup.add(undoAction);
  popup.add(redoAction);

  popup.addPopupMenuListener(new PopupMenuListener() {
    @Override public void popupMenuCanceled(PopupMenuEvent e) {}
    @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
      undoAction.setEnabled(true);
      redoAction.setEnabled(true);
    }
    @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
      JPopupMenu pop = (JPopupMenu)e.getSource();
      JTextField field = (JTextField)pop.getInvoker();
      boolean flg = field.getSelectedText()!=null;
      cutAction.setEnabled(flg);
      copyAction.setEnabled(flg);
      deleteAction.setEnabled(flg);
      undoAction.setEnabled(manager.canUndo());
      redoAction.setEnabled(manager.canRedo());
    }
  });
  tc.setComponentPopupMenu(popup);
  return popup;
}
}}

**解説 [#occ20915]
上記のサンプルでは、``JTable``のセルエディタに、``Cut``、``Copy``、``Paste``、``Delete``、``Undo``、``Redo``を行う``JPopumMenu``を設定しています。セルエディタとして使用している``JTextField``は、おなじものを使い回しているので、別のセルでの編集が持ち越されないよう、``AncestorListener``を使って表示されるたびに、``UndoManager``を空(``UndoManager#discardAllEdits()``を呼び出す)にしています。

//**参考リンク
**コメント [#we846b54]
#comment