new*_*bie 2 java swing drag-and-drop
我想将我的表的数据从一个表交换到另一个表中的同一列(注意:我只有两列).
我的问题是我无法交换价值.此外,我希望仅在同一列上启用交换,否则,表值将重置为其原始值.
这是我的代码:
JTable table_1 = new JTable(model);
table_1.setPreferredScrollableViewportSize(new Dimension(300, 120));
table_1.setDragEnabled(true);
table_1.setDropMode(DropMode.USE_SELECTION);
table_1.setTransferHandler(new TransferHelper());
table_1.setRowSelectionAllowed(false);
table_1.setCellSelectionEnabled(true);
Run Code Online (Sandbox Code Playgroud)
我的TransferHelper类:
class TransferHelper extends TransferHandler {
private static final long serialVersionUID = 1L;
public TransferHelper() {
}
@Override
public int getSourceActions(JComponent c) {
return MOVE;
}
@Override
protected Transferable createTransferable(JComponent source) {
String data = (String) ((JTable) source).getModel().getValueAt(((JTable) source).getSelectedRow(), ((JTable) source).getSelectedColumn());
return new StringSelection(data);
}
@Override
protected void exportDone(JComponent source, Transferable data, int action) {
((JTable) source).getModel().setValueAt("", ((JTable) source).getSelectedRow(), ((JTable) source).getSelectedColumn());
}
@Override
public boolean canImport(TransferSupport support) {
return true;
}
@Override
public boolean importData(TransferSupport support) {
JTable jt = (JTable) support.getComponent();
try {
jt.setValueAt(support.getTransferable().getTransferData(DataFlavor.stringFlavor), jt.getSelectedRow(), jt.getSelectedColumn());
} catch (UnsupportedFlavorException ex) {
} catch (IOException ex) {
}
return super.importData(support);
}
}
Run Code Online (Sandbox Code Playgroud)
拖放不是一个简单的过程,它非常复杂且涉及到.这种复杂性带来了灵活性.
以这种方式交换值与"移动" 本身不同.当移动某些东西时,你从源头获取它并将它放在目标中,这里我们在源和目标之间交换值,这意味着我们需要比通常通过API获得的更多信息.
首先,你需要一个自定义类来保存要导出的数据,因为我们正在移动数据,这将需要一些额外的信息,特别是源组件......
以下只是一个简单的包装器.我们可以JTable完全导出,但我想展示拖放的基本概念......
import javax.swing.JTable;
public class CellData {
private JTable table;
public CellData(JTable table) {
this.table = table;
}
public int getColumn() {
return table.getSelectedColumn();
}
public String getValue() {
int row = table.getSelectedRow();
int col = table.getSelectedColumn();
return (String) table.getValueAt(row, col);
}
public JTable getTable() {
return table;
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,我们需要一个自定义Transferable来管理我们的数据......
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
public class CellDataTransferable implements Transferable {
public static final DataFlavor CELL_DATA_FLAVOR = createConstant(CellData.class, "application/x-java-celldata");
private CellData cellData;
public CellDataTransferable(CellData cellData) {
this.cellData = cellData;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{CELL_DATA_FLAVOR};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
boolean supported = false;
for (DataFlavor available : getTransferDataFlavors()) {
if (available.equals(flavor)) {
supported = true;
}
}
return supported;
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return cellData;
}
static protected DataFlavor createConstant(Class clazz, String name) {
try {
return new DataFlavor(clazz, name);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后,TransferHandler....
public class TransferHelper extends TransferHandler {
private static final long serialVersionUID = 1L;
public TransferHelper() {
}
@Override
public int getSourceActions(JComponent c) {
return MOVE;
}
@Override
protected Transferable createTransferable(JComponent source) {
// Create the transferable
// Because I'm hacking a little, I've included the source table...
JTable table = (JTable) source;
return new CellDataTransferable(new CellData(table));
}
@Override
protected void exportDone(JComponent source, Transferable data, int action) {
}
@Override
public boolean canImport(TransferSupport support) {
// Reject the import by default...
boolean canImport = false;
// Can only import into another JTable
Component comp = support.getComponent();
if (comp instanceof JTable) {
JTable table = (JTable) comp;
// Need the location where the drop might occur
DropLocation dl = support.getDropLocation();
Point dp = dl.getDropPoint();
// Get the column at the drop point
int dragColumn = table.columnAtPoint(dp);
try {
// Get the Transferable, we need to check
// the constraints
Transferable t = support.getTransferable();
CellData cd = (CellData) t.getTransferData(CellDataTransferable.CELL_DATA_FLAVOR);
// Make sure we're not dropping onto ourselves...
if (cd.getTable() != table) {
// Do the columns match...?
if (dragColumn == cd.getColumn()) {
canImport = true;
}
}
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
return canImport;
}
@Override
public boolean importData(TransferSupport support) {
// Import failed for some reason...
boolean imported = false;
// Only import into JTables...
Component comp = support.getComponent();
if (comp instanceof JTable) {
JTable target = (JTable) comp;
// Need to know where we are importing to...
DropLocation dl = support.getDropLocation();
Point dp = dl.getDropPoint();
int dropCol = target.columnAtPoint(dp);
int dropRow = target.rowAtPoint(dp);
try {
// Get the Transferable at the heart of it all
Transferable t = support.getTransferable();
CellData cd = (CellData) t.getTransferData(CellDataTransferable.CELL_DATA_FLAVOR);
if (cd.getTable() != target) {
// Make sure the columns match
if (dropCol == cd.getColumn()) {
// Get the data from the "dropped" table
String exportValue = (String) target.getValueAt(dropRow, dropCol);
// Get the data from the "dragged" table
String importValue = cd.getValue();
// This is where we swap the values...
// Set the target/dropped tables value
target.setValueAt(importValue, dropRow, dropCol);
// Set the source/dragged tables values
JTable source = cd.getTable();
int row = source.getSelectedRow();
int col = source.getSelectedColumn();
source.setValueAt(exportValue, row, col);
imported = true;
}
}
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
return imported;
}
}
Run Code Online (Sandbox Code Playgroud)
阅读评论:P
最后,一个可运行的例子......

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.TransferHandler;
import static javax.swing.TransferHandler.MOVE;
import javax.swing.TransferHandler.TransferSupport;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
public class TableSwap {
public static void main(String[] args) {
new TableSwap();
}
public TableSwap() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JTable t1 = createTable(0);
JTable t2 = createTable(20);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0, 2));
frame.add(new JScrollPane(t1));
frame.add(new JScrollPane(t2));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected JTable createTable(int startAt) {
DefaultTableModel model = new DefaultTableModel(0, 2);
for (int index = 0; index < 10; index++) {
model.addRow(new Object[]{"0x" + (index + startAt), "1x" + (index + startAt)});
}
JTable table = new JTable(model);
table.setDragEnabled(true);
table.setDropMode(DropMode.USE_SELECTION);
table.setTransferHandler(new TransferHelper());
table.setRowSelectionAllowed(false);
table.setCellSelectionEnabled(true);
return table;
}
}
Run Code Online (Sandbox Code Playgroud)
更新为仅支持单个表
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.TransferHandler;
import static javax.swing.TransferHandler.MOVE;
import javax.swing.TransferHandler.TransferSupport;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
public class TableSwap {
public static void main(String[] args) {
new TableSwap();
}
public TableSwap() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JTable t1 = createTable(0);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(t1));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected JTable createTable(int startAt) {
DefaultTableModel model = new DefaultTableModel(0, 2);
for (int index = 0; index < 10; index++) {
model.addRow(new Object[]{"0x" + (index + startAt), "1x" + (index + startAt)});
}
JTable table = new JTable(model);
table.setDragEnabled(true);
table.setDropMode(DropMode.USE_SELECTION);
table.setTransferHandler(new TransferHelper());
table.setRowSelectionAllowed(false);
table.setCellSelectionEnabled(true);
return table;
}
public class CellData {
private final Object value;
private final int col;
private final JTable table;
private final int row;
public CellData(JTable source) {
this.col = source.getSelectedColumn();
this.row = source.getSelectedRow();
this.value = source.getValueAt(row, col);
this.table = source;
}
public int getColumn() {
return col;
}
public Object getValue() {
return value;
}
public JTable getTable() {
return table;
}
public boolean swapValuesWith(int targetRow, int targetCol) {
boolean swapped = false;
if (targetCol == col) {
Object exportValue = table.getValueAt(targetRow, targetCol);
table.setValueAt(value, targetRow, targetCol);
table.setValueAt(exportValue, row, col);
swapped = true;
}
return swapped;
}
}
public static final DataFlavor CELL_DATA_FLAVOR = createConstant(CellData.class, "application/x-java-celldata");
public class CellDataTransferable implements Transferable {
private CellData cellData;
public CellDataTransferable(CellData cellData) {
this.cellData = cellData;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{CELL_DATA_FLAVOR};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
boolean supported = false;
for (DataFlavor available : getTransferDataFlavors()) {
if (available.equals(flavor)) {
supported = true;
}
}
return supported;
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return cellData;
}
}
static protected DataFlavor createConstant(Class clazz, String name) {
try {
return new DataFlavor(clazz, name);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public class TransferHelper extends TransferHandler {
private static final long serialVersionUID = 1L;
public TransferHelper() {
}
@Override
public int getSourceActions(JComponent c) {
return MOVE;
}
@Override
protected Transferable createTransferable(JComponent source) {
// Create the transferable
JTable table = (JTable) source;
int row = table.getSelectedRow();
int col = table.getSelectedColumn();
Object value = table.getValueAt(row, col);
return new CellDataTransferable(new CellData(table));
}
@Override
protected void exportDone(JComponent source, Transferable data, int action) {
}
@Override
public boolean canImport(TransferSupport support) {
// Reject the import by default...
boolean canImport = false;
// Can only import into another JTable
Component comp = support.getComponent();
if (comp instanceof JTable) {
JTable target = (JTable) comp;
// Need the location where the drop might occur
DropLocation dl = support.getDropLocation();
Point dp = dl.getDropPoint();
// Get the column at the drop point
int dragColumn = target.columnAtPoint(dp);
try {
// Get the Transferable, we need to check
// the constraints
Transferable t = support.getTransferable();
CellData cd = (CellData) t.getTransferData(CELL_DATA_FLAVOR);
// Make sure we're not dropping onto ourselves...
if (cd.getTable() == target) {
// Do the columns match...?
if (dragColumn == cd.getColumn()) {
canImport = true;
}
}
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
return canImport;
}
@Override
public boolean importData(TransferSupport support) {
// Import failed for some reason...
boolean imported = false;
// Only import into JTables...
Component comp = support.getComponent();
if (comp instanceof JTable) {
JTable target = (JTable) comp;
// Need to know where we are importing to...
DropLocation dl = support.getDropLocation();
Point dp = dl.getDropPoint();
int dropCol = target.columnAtPoint(dp);
int dropRow = target.rowAtPoint(dp);
try {
// Get the Transferable at the heart of it all
Transferable t = support.getTransferable();
CellData cd = (CellData) t.getTransferData(CELL_DATA_FLAVOR);
if (cd.getTable() == target) {
if (cd.swapValuesWith(dropRow, dropCol)) {
imported = true;
}
}
} catch (UnsupportedFlavorException | IOException ex) {
ex.printStackTrace();
}
}
return imported;
}
}
}
Run Code Online (Sandbox Code Playgroud)