TITLE:JTableの編集にセルより大きなセルエディタを使用
#navi(../)
*JTableの編集にセルより大きなセルエディタを使用 [#u7405edd]
>編集者:[[Terai Atsuhiro>terai]]~
作成日:2006-08-28~
更新日:&lastmod;

#contents

**概要 [#o93f3deb]
通常のセルエディタではなく、セルより大きなアイコンを選択する為のセルエディタを使用してJTableを編集します。

#screenshot

**サンプルコード [#p6d316e9]
#code{{
class IconTable extends JTable {
  private final MyGlassPane panel = new MyGlassPane();
  private FocusTraversalPolicy policy = new MyFocusTraversalPolicy();
  private FocusTraversalPolicy ftp;
  private final EditorFromList editor;
  private final JFrame frame;
  private Rectangle rect;

  public IconTable(JFrame _frame, TableModel model, Vector list) {
    super(model);
    setDefaultRenderer(Object.class, new TestRenderer());
    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    initCellSize(50);
    frame = _frame;
    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent me) {
        startEditing();
      }
    });
    editor = new EditorFromList(list);
    editor.addKeyListener(new KeyAdapter() {
      public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==KeyEvent.VK_ESCAPE) {
          cancelEditing();
        }
      }
    });
    editor.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent me) {
        changeValue(me.getPoint());
      }
    });
    panel.add(editor);
    frame.setGlassPane(panel);
    panel.setVisible(false);
  }
  private void initCellSize(int size) {
    setRowHeight(size);
    JTableHeader tableHeader = getTableHeader();
    tableHeader.setResizingAllowed(false);
    tableHeader.setReorderingAllowed(false);
    TableColumnModel m = getColumnModel();
    for(int i=0;i<m.getColumnCount();i++) {
      TableColumn col = m.getColumn(i);
      col.setMinWidth(size);
      col.setMaxWidth(size);
    }
    setBorder(BorderFactory.createLineBorder(Color.BLACK));
  }
  private void initEditor() {
    Dimension dim = editor.getPreferredSize();
    rect = getCellRect(getSelectedRow(), getSelectedColumn(), true);
    int iv = (dim.width-rect.width)/2;
    Point p = SwingUtilities.convertPoint(this,
                rect.getLocation(), panel);
    rect.setRect(p.x-iv, p.y-iv, dim.width, dim.height);
    editor.setBounds(rect);
    Object o = getValueAt(getSelectedRow(), getSelectedColumn());
    editor.setSelectedValue(o, true);
  }
  public void startEditing() {
    initEditor();
    ftp = frame.getFocusTraversalPolicy();
    panel.setVisible(true);
    editor.requestFocusInWindow();
    frame.setFocusTraversalPolicy(policy);
  }
  private void cancelEditing() {
    frame.setFocusTraversalPolicy(ftp);
    panel.setVisible(false);
  }
  private void changeValue(Point p) {
    frame.setFocusTraversalPolicy(ftp);
    int index = editor.locationToIndex(p);
    Object o = editor.getModel().getElementAt(index);
    if(o != null) {
      setValueAt(o, getSelectedRow(), getSelectedColumn());
    }
    panel.setVisible(false);
  }
}
}}
-&jnlp;
-&jar;
-&zip;

**解説 [#t6dfc826]
上記のサンプルでは、JTableのセルをクリックするとそのセル上にセルエディタが表示されて編集できるようになっています。

通常のセルエディタは使用しないため、すべてのセルを編集不可にしています。かわりにセルをクリックしたときに、フレームのGlassPaneを有効にして、そこにJListで作成したアイコン選択エディタや、その影などを描画しています。

このようにGlassPaneを使用しているため、フレームの外にセルエディタを描画することができません。このためサンプルではJTableの周りに余白をかなり多めにとっています。JTableからはみ出す場合(端の方のセルを編集する場合)は、セルエディタの表示位置を内部にずらすように変更するようにしたほうがいいかもしれません。

**参考リンク [#yc6dd5bb]
-[[XP Style Icons - Windows Application Icon, Software XP Icons>http://www.icongalore.com/]]
--アイコンを利用しています。

**コメント [#n6dadda3]
- 表示をアニメーションさせたり、音を出したりしても面白そうです。 -- [[terai]] &new{2006-10-29 (日) 02:03:44};

#comment