Swing/DragRowsAnotherTable のバックアップ(No.3)
- バックアップ一覧
 - 差分 を表示
 - 現在との差分 を表示
 - 現在との差分 - Visual を表示
 - ソース を表示
 - Swing/DragRowsAnotherTable へ行く。
  
- 1 (2009-09-28 (月) 14:28:36)
 - 2 (2009-09-30 (水) 12:43:21)
 - 3 (2009-11-16 (月) 10:51:53)
 - 4 (2010-12-20 (月) 22:02:47)
 - 5 (2013-01-05 (土) 19:55:46)
 - 6 (2014-02-20 (木) 19:52:46)
 - 7 (2014-03-18 (火) 18:52:24)
 - 8 (2014-05-02 (金) 12:45:50)
 - 9 (2014-09-30 (火) 00:50:15)
 - 10 (2014-11-30 (日) 00:54:45)
 - 11 (2015-01-03 (土) 06:19:07)
 - 12 (2015-03-18 (水) 18:48:37)
 - 13 (2015-12-15 (火) 17:06:08)
 - 14 (2017-06-02 (金) 15:28:43)
 - 15 (2017-08-15 (火) 14:46:43)
 - 16 (2017-11-17 (金) 17:46:30)
 - 17 (2018-02-24 (土) 19:51:30)
 - 18 (2019-05-11 (土) 15:54:34)
 - 19 (2019-05-12 (日) 18:45:55)
 - 20 (2019-09-26 (木) 20:50:29)
 - 21 (2019-10-15 (火) 17:34:55)
 - 22 (2019-10-23 (水) 21:26:55)
 - 23 (2021-05-23 (日) 12:42:25)
 - 24 (2025-01-03 (金) 08:57:02)
 - 25 (2025-01-03 (金) 09:01:23)
 - 26 (2025-01-03 (金) 09:02:38)
 - 27 (2025-01-03 (金) 09:03:21)
 - 28 (2025-01-03 (金) 09:04:02)
 - 29 (2025-06-19 (木) 12:41:37)
 - 30 (2025-06-19 (木) 12:43:47)
 
 
TITLE:JTableの行を別のJTableにドラッグして移動
Posted by terai at 2009-09-28
JTableの行を別のJTableにドラッグして移動
JTableの行を別のJTableにDrag&Dropで移動します。
- &jnlp;
 - &jar;
 - &zip;
 
#screenshot
サンプルコード
class TableRowTransferHandler extends TransferHandler {
  private int[] rows    = null;
  private int addIndex  = -1; //Location where items were added
  private int addCount  = 0;  //Number of items added.
  private final DataFlavor localObjectFlavor;
  private Object[] transferedObjects = null;
  private JComponent source = null;
  public TableRowTransferHandler() {
    localObjectFlavor = new ActivationDataFlavor(
      Object[].class, DataFlavor.javaJVMLocalObjectMimeType, "Array of items");
  }
  @Override protected Transferable createTransferable(JComponent c) {
    source = c;
    JTable table = (JTable) c;
    DefaultTableModel model = (DefaultTableModel)table.getModel();
    ArrayList<Object> list = new ArrayList<Object>();
    for(int i: rows = table.getSelectedRows())
      list.add(model.getDataVector().elementAt(i));
    transferedObjects = list.toArray();
    return new DataHandler(transferedObjects,localObjectFlavor.getMimeType());
  }
  @Override public boolean canImport(TransferHandler.TransferSupport info) {
    JTable t = (JTable)info.getComponent();
    boolean b = info.isDrop()&&info.isDataFlavorSupported(localObjectFlavor);
    //XXX bug?
    t.setCursor(b?DragSource.DefaultMoveDrop:DragSource.DefaultMoveNoDrop);
    return b;
  }
  @Override public int getSourceActions(JComponent c) {
    return TransferHandler.COPY_OR_MOVE;
  }
  @Override public boolean importData(TransferHandler.TransferSupport info) {
    JTable target = (JTable)info.getComponent();
    JTable.DropLocation dl = (JTable.DropLocation)info.getDropLocation();
    DefaultTableModel model = (DefaultTableModel)target.getModel();
    int index = dl.getRow();
    int max = model.getRowCount();
    if(index<0 || index>max) index = max;
    addIndex = index;
    target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    try {
      Object[] values =
        (Object[])info.getTransferable().getTransferData(localObjectFlavor);
      if(source==target) addCount = values.length;
      for(int i=0;i<values.length;i++) {
        int idx = index++;
        model.insertRow(idx, (Vector)values[i]);
        target.getSelectionModel().addSelectionInterval(idx, idx);
      }
      return true;
    }catch(Exception ufe) { ufe.printStackTrace(); }
    return false;
  }
  @Override protected void exportDone(JComponent c, Transferable t, int act) {
    cleanup(c, act == TransferHandler.MOVE);
  }
  private void cleanup(JComponent src, boolean remove) {
    if(remove && rows != null) {
      JTable table = (JTable)src;
      src.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
      DefaultTableModel model = (DefaultTableModel)table.getModel();
      if(addCount > 0) {
        for(int i=0;i<rows.length;i++) {
          if(rows[i]>=addIndex) { rows[i] += addCount; }
        }
      }
      for(int i=rows.length-1;i>=0;i--) model.removeRow(rows[i]);
    }
    rows     = null;
    addCount = 0;
    addIndex = -1;
  }
}
解説
上記のサンプルでは、一つのJTable内での行の並べ替えを行うTransferHandlerを使ってJTableの行をドラック&ドロップ、並べ替えを元にTableRowTransferHandlerを作成し、JTable間での行移動もできるようになっています。
以下のように、JTable#setFillsViewportHeight(true)で、JTable自体の高さを拡張しておかないと、行が一つもない状態でドロップができなくなります。
TransferHandler handler = new TableRowTransferHandler();
table.getSelectionModel().setSelectionMode(
            ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setTransferHandler(handler);
table.setDropMode(DropMode.INSERT_ROWS);
table.setDragEnabled(true);
table.setFillsViewportHeight(true);
WindowsLnFでカーソルのチラつき防止のために、TransferHandler#canImport(...)内でJTable#setCursor(...)をしているため、ディスクトップなどからファイルをドラッグしてドロップ不可カーソルが表示されるとマウスをリリースしたあともそのカーソルが表示されたままになるバグがあります。