我有一些行的JTable。我想当用鼠标移动一行(拖放)时,该行与鼠标和表行一起移动,以便在鼠标移动时重新排序(例如移动JTable的列)。
这jsfiddle正是我想要的,但是我必须在java swing(或下面的gif图像)中进行操作。示例来自here,但我听不懂。
我的TransferHandler:
public class TableRowTransferHandler extends TransferHandler {
private final DataFlavor localObjectFlavor = new ActivationDataFlavor(Integer.class, "application/x-java-Integer;class=java.lang.Integer", "Integer Row Index");
private JTable table = null;
private static final Logger logger = Logger.getLogger(TableRowTransferHandler.class.getName());
public TableRowTransferHandler(JTable table) {
this.table = table;
}
@Override
protected Transferable createTransferable(JComponent c) {
assert (c == table);
return new DataHandler(table.getSelectedRow(), localObjectFlavor.getMimeType());
}
@Override
public boolean canImport(TransferHandler.TransferSupport info) {
boolean b = info.getComponent() == table && info.isDrop() && info.isDataFlavorSupported(localObjectFlavor);
table.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();
int index = dl.getRow();
int max = table.getModel().getRowCount();
if (index < 0 || index > max) {
index = max;
}
target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
try {
Integer rowFrom = (Integer) info.getTransferable().getTransferData(localObjectFlavor);
if (rowFrom != -1 && rowFrom != index) {
((Reorderable) table.getModel()).reorder(rowFrom, index);
if (index > rowFrom) {
index--;
}
target.getSelectionModel().addSelectionInterval(index, index);
return true;
}
} catch (UnsupportedFlavorException | IOException e) {
e.printStackTrace();
logger.log(Level.SEVERE, null, e);
}
return false;
}
@Override
protected void exportDone(JComponent c, Transferable t, int act) {
if ((act == TransferHandler.MOVE) || (act == TransferHandler.NONE)) {
table.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
这是我用于JTable的简单设置:
childrenTable.setDragEnabled(true);
childrenTable.setDropMode(DropMode.INSERT);
childrenTable.setTransferHandler(new TableRowTransferHandler(childrenTable));
childrenTable.setRowSelectionAllowed(true);
childrenTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
目前,当您使用鼠标在行之间移动行时,只有一条粗线(如下面图片中的红色椭圆所示)。如果不可能做这样的行移动,我希望此粗线显示在整行中(不仅在一个单元格中)。
最佳答案
阅读Swing教程中有关拖放的部分,以了解基础知识。
这是一些我在网上找到的带有自定义TransferHandler
来支持JTable的旧代码:
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.IOException;
public class DnD_Demo extends JFrame {
public DnD_Demo() {
setTitle("DnD Demo (Version 3)");
JTextArea tips = new JTextArea("1. Select a row in Table A. " +
"Press the row again and drag. \n " +
"As you drag the cursor icon over Table B, the row that is currently under the cursor highlights " +
"- the new data will be inserted after the selected row. \n " +
"Drop the row onto Table B. Note that the row has been removed from Table A, " +
"and now appears in Table B. \n" +
"2. Select two rows from Table A and drop onto Table B. " +
"Now there are two new rows in Table B. ");
tips.setEditable(false);
tips.setBackground(new Color(255,255,204));
tips.setBorder(new LineBorder(Color.orange,5));
getContentPane().add(tips,BorderLayout.NORTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridLayout(2,1));
panel.add(createTable("Table A"));
panel.add(createTable("Table B"));
getContentPane().add(panel,BorderLayout.CENTER);
pack();
}
private JPanel createTable(String tableId) {
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Column 0");
model.addColumn("Column 1");
model.addColumn("Column 2");
model.addColumn("Column 3");
model.addRow(new String[]{tableId+" 00", tableId+" 01", tableId+" 02", tableId+" 03"});
model.addRow(new String[]{tableId+" 10", tableId+" 11", tableId+" 12", tableId+" 13"});
model.addRow(new String[]{tableId+" 20", tableId+" 21", tableId+" 22", tableId+" 23"});
model.addRow(new String[]{tableId+" 30", tableId+" 31", tableId+" 32", tableId+" 33"});
JTable table = new JTable(model);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(400,100));
table.setDragEnabled(true);
table.setTransferHandler(new TableTransferHandler());
JPanel panel = new JPanel();
panel.add(scrollPane);
panel.setBorder(BorderFactory.createTitledBorder(tableId));
return panel;
}
public static void main(String[] args) {
new DnD_Demo().setVisible(true);
}
abstract class StringTransferHandler extends TransferHandler {
protected abstract String exportString(JComponent c);
protected abstract void importString(JComponent c, String str);
protected abstract void cleanup(JComponent c, boolean remove);
protected Transferable createTransferable(JComponent c) {
return new StringSelection(exportString(c));
}
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
public boolean importData(JComponent c, Transferable t) {
if (canImport(c, t.getTransferDataFlavors())) {
try {
String str = (String)t.getTransferData(DataFlavor.stringFlavor);
importString(c, str);
return true;
} catch (UnsupportedFlavorException ufe) {
} catch (IOException ioe) {
}
}
return false;
}
protected void exportDone(JComponent c, Transferable data, int action) {
cleanup(c, action == MOVE);
}
public boolean canImport(JComponent c, DataFlavor[] flavors) {
for (int i = 0; i < flavors.length; i++) {
if (DataFlavor.stringFlavor.equals(flavors[i])) {
return true;
}
}
return false;
}
}
class TableTransferHandler extends StringTransferHandler {
public JTable target;
public int[] rows = null;
public int addIndex = -1; //Location where items were added
public int addCount = 0; //Number of items added.
protected String exportString(JComponent c) {
JTable table = (JTable)c;
rows = table.getSelectedRows();
int colCount = table.getColumnCount();
StringBuffer buff = new StringBuffer();
for (int i = 0; i < rows.length; i++) {
for (int j = 0; j < colCount; j++) {
Object val = table.getValueAt(rows[i], j);
buff.append(val == null ? "" : val.toString());
if (j != colCount - 1) {
buff.append(",");
}
}
if (i != rows.length - 1) {
buff.append("\n");
}
}
return buff.toString();
}
protected void importString(JComponent c, String str) {
target = (JTable)c;
DefaultTableModel model = (DefaultTableModel)target.getModel();
int index = target.getSelectedRow();
//Prevent the user from dropping data back on itself.
//For example, if the user is moving rows #4,#5,#6 and #7 and
//attempts to insert the rows after row #5, this would
//be problematic when removing the original rows.
//So this is not allowed.
if (rows != null && index >= rows[0] - 1 &&
index <= rows[rows.length - 1]) {
rows = null;
return;
}
int max = model.getRowCount();
if (index < 0) {
index = max;
} else {
index++;
if (index > max) {
index = max;
}
}
addIndex = index;
String[] values = str.split("\n");
addCount = values.length;
int colCount = target.getColumnCount();
for (int i = 0; i < values.length ; i++) {
model.insertRow(index++, values[i].split(","));
}
//If we are moving items around in the same table, we
//need to adjust the rows accordingly, since those
//after the insertion point have moved.
if (rows!= null && addCount > 0) {
for (int i = 0; i < rows.length; i++) {
if (rows[i] > addIndex) {
rows[i] += addCount;
}
}
}
}
protected void cleanup(JComponent c, boolean remove) {
JTable source = (JTable)c;
if (remove && rows != null) {
DefaultTableModel model =
(DefaultTableModel)source.getModel();
for (int i = rows.length - 1; i >= 0; i--) {
model.removeRow(rows[i]);
}
}
rows = null;
addCount = 0;
addIndex = -1;
}
}
}