JTableの行をドラッグ&ドロップ
Total: 21181
, Today: 2
, Yesterday: 1
Posted by aterai at
Last-modified:
概要
JTable
の行を選択し、その順序をドラッグ&ドロップで入れ替えます。
Screenshot
Advertisement
サンプルコード
class DnDTable extends JTable implements DragGestureListener, Transferable {
private static final String NAME = "test";
private static final DataFlavor FLAVOR =
new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME);
private static final Color LINE_COLOR = new Color(255, 100, 100);
private final 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();
new DragSource().createDefaultDragGestureRecognizer(
(Component) this, DnDConstants.ACTION_COPY_OR_MOVE,
(DragGestureListener) this);
}
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (targetIndex >= 0) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setPaint(LINE_COLOR);
g2.fill(targetLine);
g2.dispose();
}
}
private void initTargetLine(Point p) {
Rectangle2D testArea = new Rectangle2D.Float();
int cellHeight = getRowHeight();
int lineWidth = getWidth();
int lineHeight = 2;
int modelSize = getRowCount();
targetIndex = -1;
for (int i = 0; i < modelSize; i++) {
testArea.setBounds(
0, cellHeight * i - cellHeight / 2, lineWidth, cellHeight);
if (testArea.contains(p)) {
targetIndex = i;
targetLine.setBounds(0, i * cellHeight, lineWidth, lineHeight);
break;
}
}
if (targetIndex < 0) {
targetIndex = modelSize;
targetLine.setBounds(
0, targetIndex * cellHeight - lineHeight, lineWidth, 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,
new TableDragSourceListener());
} catch (InvalidDnDOperationException idoe) {
idoe.printStackTrace();
}
}
// Interface: Transferable
@Override public Object getTransferData(DataFlavor flavor) {
return this;
}
@Override public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] {FLAVOR};
}
@Override public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.getHumanPresentableName().equals(NAME);
}
class CDropTargetListener implements DropTargetListener {
@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());
setCursor(DragSource.DefaultMoveDrop);
} else {
e.rejectDrag();
setCursor(DragSource.DefaultMoveNoDrop);
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();
if (isDropAcceptable(e)) {
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);
}
e.dropComplete(false);
setCursor(Cursor.getDefaultCursor());
targetIndex = -1;
repaint();
}
private boolean isDragAcceptable(DropTargetDragEvent e) {
DataFlavor[] f = e.getCurrentDataFlavors();
return isDataFlavorSupported(f[0]);
}
private boolean isDropAcceptable(DropTargetDropEvent e) {
Transferable t = e.getTransferable();
DataFlavor[] f = t.getTransferDataFlavors();
return isDataFlavorSupported(f[0]);
}
}
}
View in GitHub: Java, Kotlin解説
ドラッグソースとドラッグターゲットをどちらもJTable
にして、行の入れ替えがドラッグ&ドロップで可能になっています。
このサンプルのドラッグ&ドロップの手順は、行の入れ替え処理などを除けばJListの項目をドラッグ&ドロップと同等です。
参考リンク
- JListの項目をドラッグ&ドロップ
- JTable自体の高さを拡張
- TransferHandlerを使ってJTableの行をドラッグ&ドロップ、並べ替え
Java 1.6.0
以上で複数行を選択して移動を行う場合のサンプル
- JTableの行を別のJTableにドラッグして移動
- JTree間でのドラッグ&ドロップによるノードの移動