• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JTableの行をドラッグ&ドロップ
#navi(../)
#tags(JTable, DragAndDrop)
RIGHT:Posted by &author(aterai); at 2007-04-02
*JTableの行をドラッグ&ドロップ [#a9cb5120]
``JTable``の行をドラッグ&ドロップで入れ替えます。
---
title: JTableの行をドラッグ&ドロップ
tags: [JTable, DragAndDrop]
author: aterai
pubdate: 2007-04-02T16:29:09+09:00
---
* 概要 [#a9cb5120]
`JTable`の行をドラッグ&ドロップで入れ替えます。

-&jnlp;
-&jar;
-&zip;
#download(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTLl0NAFoI/AAAAAAAAAX0/su1r-c7f4V0/s800/DnDTable.png)

//#screenshot
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTLl0NAFoI/AAAAAAAAAX0/su1r-c7f4V0/s800/DnDTable.png)

**サンプルコード [#bea7b546]
* サンプルコード [#bea7b546]
#code(link){{
class DnDTable extends JTable implements DragGestureListener, DragSourceListener, Transferable {
  private static final String NAME = "test";
  private static final Color lineColor = new Color(255,100,100);
  private Rectangle2D targetLine = new Rectangle2D.Float();
  private int draggedIndex = -1;
  private int targetIndex  = -1;
  public DnDTable(TableModel model) {
    super(model);
    DropTarget dropTarget = new DropTarget(this,
      DnDConstants.ACTION_COPY_OR_MOVE, new CDropTargetListener(), true);
    DragSource dragSource = new DragSource();
    dragSource.createDefaultDragGestureRecognizer((Component)this,
      DnDConstants.ACTION_COPY_OR_MOVE, (DragGestureListener)this);
  }
  @Override public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if(targetIndex>=0) {
      Graphics2D g2 = (Graphics2D)g;
      g2.setPaint(lineColor);
      g2.fill(targetLine);
    }
  }
  private void initTargetLine(Point p) {
    Rectangle2D testArea = new Rectangle2D.Float();
    int cellHeight = getRowHeight();
    int lineWidht  = getWidth();
    int lineHeight = 2;
    int modelSize  = getRowCount();
    targetIndex = -1;
    for(int i=0;i<modelSize;i++) {
      testArea.setRect(0, cellHeight*i-(cellHeight/2), lineWidht, cellHeight);
      if(testArea.contains(p)) {
        targetIndex = i;
        targetLine.setRect(0, i*cellHeight, lineWidht, lineHeight);
        break;
      }
    }
    if(targetIndex<0) {
      targetIndex = modelSize;
      targetLine.setRect(0, targetIndex*cellHeight-lineHeight, lineWidht, lineHeight);
    }
  }
  // Interface: DragGestureListener
  @Override public void dragGestureRecognized(DragGestureEvent e) {
    if(getSelectedRowCount()>1) return;
    draggedIndex = rowAtPoint(e.getDragOrigin());
    if(draggedIndex<0) return;
    try{
      e.startDrag(DragSource.DefaultMoveDrop, (Transferable)this, (DragSourceListener)this);
    }catch(InvalidDnDOperationException idoe) {}
  }
  // Interface: DragSourceListener
  @Override public void dragEnter(DragSourceDragEvent e) {
    e.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
  }
  @Override public void dragExit(DragSourceEvent e) {
    e.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
  }
  @Override public void dragOver(DragSourceDragEvent e) {}
  @Override public void dropActionChanged(DragSourceDragEvent e) {}
  @Override public void dragDropEnd(DragSourceDropEvent e) {}
  // Interface: Transferable
  private final DataFlavor FLAVOR
    = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME);
  @Override public Object getTransferData(DataFlavor flavor) {
    return this;
  }
  @Override public DataFlavor[] getTransferDataFlavors() {
    DataFlavor[] f = new DataFlavor[1];
    f[0] = this.FLAVOR;
    return f;
  }
  @Override public boolean isDataFlavorSupported(DataFlavor flavor) {
    return flavor.getHumanPresentableName().equals(NAME);
  }
 

  class CDropTargetListener implements DropTargetListener{
    // DropTargetListener interface
    @Override public void dragExit(DropTargetEvent e) {
      targetIndex = -1;
      repaint();
    }
    @Override public void dragEnter(DropTargetDragEvent e) {
      if(isDragAcceptable(e)) {
        e.acceptDrag(e.getDropAction());
      }else{
        e.rejectDrag();
      }
    }
    @Override public void dragOver(final DropTargetDragEvent e) {
      if(isDragAcceptable(e)) {
        e.acceptDrag(e.getDropAction());
      }else{
        e.rejectDrag();
        return;
      }
      initTargetLine(e.getLocation());
      repaint();
    }
    @Override public void dropActionChanged(DropTargetDragEvent e) {
      // if(isDragAcceptable(e)) e.acceptDrag(e.getDropAction());
      // else e.rejectDrag();
    }
    @Override public void drop(DropTargetDropEvent e) {
      DefaultTableModel model = (DefaultTableModel)getModel();
      Transferable t = e.getTransferable();
      DataFlavor[] f = t.getTransferDataFlavors();
      try {
        if(isDropAcceptable(e)) {
          Component comp = (Component) t.getTransferData(f[0]);
          if(targetIndex==draggedIndex) {
            setRowSelectionInterval(targetIndex,targetIndex);
          }else{
            int tg = (targetIndex<draggedIndex)?targetIndex:targetIndex-1;
            model.moveRow(draggedIndex,draggedIndex,tg);
            setRowSelectionInterval(tg,tg);
          }
          e.dropComplete(true);
        }else{
          e.dropComplete(false);
        }
      }catch(UnsupportedFlavorException ex) {
        e.dropComplete(false);
      }catch(IOException ie) {
        e.dropComplete(false);
      }
      e.dropComplete(false);
      targetIndex = -1;
      repaint();
    }
    public boolean isDragAcceptable(DropTargetDragEvent e) {
      DataFlavor[] f = e.getCurrentDataFlavors();
      return isDataFlavorSupported(f[0]);
    }
    public boolean isDropAcceptable(DropTargetDropEvent e) {
      Transferable t = e.getTransferable();
      DataFlavor[] f = t.getTransferDataFlavors();
      return isDataFlavorSupported(f[0]);
    }
  }
}
}}

**解説 [#weac537f]
ドラッグソースとドラッグターゲットをどちらも``JTable``にして、行の入れ替えがドラッグ&ドロップで出来るようになっています。
* 解説 [#weac537f]
ドラッグソースとドラッグターゲットをどちらも`JTable`にして、行の入れ替えがドラッグ&ドロップで出来るようになっています。

このサンプルのドラッグ&ドロップの手順は、行の入れ替え処理などを除けば、[[JListの項目をドラッグ&ドロップ>Swing/DnDList]]とほぼ同一です。

- 複数行を選択しての移動には対応していません。
-- ``Java 1.6.0``以上で複数行選択して移動する方法: [[TransferHandlerを使ってJTableの行をドラック&ドロップ、並べ替え>Swing/DnDReorderTable]]
-- `Java 1.6.0`以上で複数行選択して移動する方法: [[TransferHandlerを使ってJTableの行をドラッグ&ドロップ、並べ替え>Swing/DnDReorderTable]]

**参考リンク [#cef5dec4]
* 参考リンク [#cef5dec4]
- [[JListの項目をドラッグ&ドロップ>Swing/DnDList]]
- [[JTable自体の高さを拡張>Swing/FillsViewportHeight]]
- [[TransferHandlerを使ってJTableの行をドラック&ドロップ、並べ替え>Swing/DnDReorderTable]]
- [[TransferHandlerを使ってJTableの行をドラッグ&ドロップ、並べ替え>Swing/DnDReorderTable]]
- [[JTableの行を別のJTableにドラッグして移動>Swing/DragRowsAnotherTable]]

**コメント [#icf126b7]
* コメント [#icf126b7]
#comment