gpt4 book ai didi

java - 如何禁止两个 JTable 之间的拖放?

转载 作者:太空宇宙 更新时间:2023-11-04 07:04:08 25 4
gpt4 key购买 nike

我有两个 JTable,它们的设置使您可以拖放每个 JTable 中的行。问题是它允许我将一行从一个 JTable 拖到另一个 JTable,而我正在尝试找出如何阻止这种情况。我只希望用户能够在同一个 JTable 中拖放一行。

换句话说,当我在当前表格之外拖动一行并将鼠标悬停在空白面板空间上时,鼠标光标会显示一个带有对角线的圆圈,这就是我想要的。 但是,当我将鼠标拖动到另一个表上时,它会显示小矩形“放置”图标,这正是我试图阻止的。当用户尝试将此行拖动到其他表格的顶部时,我希望出现带有对角线的小圆圈。

这是一个演示该问题的工作示例:

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DragSource;
import java.util.ArrayList;
import java.util.List;

import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.table.AbstractTableModel;

public class JTableDnD extends JFrame
{

private JTable tableA;
private JTable tableB;

public JTableDnD()
{
// *** Create First Table ***

List<Object[]> dataA = new ArrayList<Object[]>();
dataA.add(new Object[] {"A1", "A1"});
dataA.add(new Object[] {"A2", "A2"});
dataA.add(new Object[] {"A3", "A3"});

List<String> columnsA = new ArrayList<String>();
columnsA.add("Column 1");
columnsA.add("Column 2");

tableA = new JTable(new TableModel(columnsA, dataA));

tableA.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tableA.setDragEnabled(true);
tableA.setDropMode(DropMode.INSERT_ROWS);
tableA.setFillsViewportHeight(true);
tableA.setTransferHandler(new TableTransferHandler(tableA));

JScrollPane scrollPaneA = new JScrollPane(tableA);

// *** Create Second Table ***

List<Object[]> dataB = new ArrayList<Object[]>();
dataB.add(new Object[] {"B1", "B1"});
dataB.add(new Object[] {"B2", "B2"});
dataB.add(new Object[] {"B3", "B3"});

List<String> columnsB = new ArrayList<String>();
columnsB.add("Column 1");
columnsB.add("Column 2");

tableB = new JTable(new TableModel(columnsB, dataB));

tableB.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tableB.setDragEnabled(true);
tableB.setDropMode(DropMode.INSERT_ROWS);
tableB.setFillsViewportHeight(true);
tableB.setTransferHandler(new TableTransferHandler(tableB));

JScrollPane scrollPaneB = new JScrollPane(tableB);

// *** Add ScrollPanes to Panel ***

this.getContentPane().setLayout(new FlowLayout());

add(scrollPaneA);

JPanel emptyPanel = new JPanel();
emptyPanel.setPreferredSize(new Dimension(100, 200));
add(emptyPanel);

add(scrollPaneB);

} // end JTableDnD constructor

private static void createAndShowGUI()
{
JFrame frame = new JTableDnD();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}

public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

createAndShowGUI();

}

});
}
}


interface Reorderable
{
public void reorder(int from, int to);
}


class TableModel extends AbstractTableModel implements Reorderable
{

private List<String> columnNames;
private List<Object[]> data;

public TableModel(List<String> columnNames, List<Object[]> data)
{
super();
this.columnNames = columnNames;
this.data = data;
}

@Override
public void reorder(int from, int to)
{
if (from < to)
{
to--;
}

Object[] row = data.remove(from);

data.add(to, row);

fireTableDataChanged();
}

@Override
public int getRowCount()
{
return data.size();
}

@Override
public int getColumnCount()
{
return columnNames.size();
}

@Override
public String getColumnName(int column)
{
return columnNames.get(column);
}

@Override
public Object getValueAt(int rowIndex, int columnIndex)
{
return data.get(rowIndex)[columnIndex];
}

} // end TableModel


class TableTransferHandler extends TransferHandler
{
private final DataFlavor localObjectFlavor = new ActivationDataFlavor(Integer.class, DataFlavor.javaJVMLocalObjectMimeType, "Integer Row Index");

private JTable table = null;


public TableTransferHandler(JTable table)
{
this.table = table;
}


@Override
protected Transferable createTransferable(JComponent component)
{
return new DataHandler(new Integer(table.getSelectedRow()), localObjectFlavor.getMimeType());
}


@Override
public boolean canImport(TransferHandler.TransferSupport support)
{
boolean b = support.getComponent() == table &&
support.isDrop() &&
support.isDataFlavorSupported(localObjectFlavor);

table.setCursor(b ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop);

return b;
}


@Override
public int getSourceActions(JComponent component)
{
return TransferHandler.COPY_OR_MOVE;
}


@Override
public boolean importData(TransferHandler.TransferSupport support)
{
JTable target = (JTable) support.getComponent();

JTable.DropLocation dropLocation = (JTable.DropLocation) support.getDropLocation();

int index = dropLocation.getRow();

int max = table.getModel().getRowCount();

if (index < 0 || index > max)
{
index = max;
}

target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

try
{
Integer rowFrom = (Integer) support.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 (Exception e)
{
e.printStackTrace();
}

return false;
}


@Override
protected void exportDone(JComponent component, Transferable transferable, int action)
{
if (action == TransferHandler.MOVE)
{
table.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
} // end TableTransferHandler

我相信我需要向 canImport() 方法添加一些额外的逻辑,以确保要删除的行来自同一个表,但我似乎无法弄清楚。我尝试检查传递到 canImport() 的 TransferSupport 对象内的数据,但它似乎没有任何返回确切 JTable 对象源的函数。

最佳答案

在简化的 Swing DnD 中,不支持获取可传输的源。 TransferSupport` 返回的组件是 drop 的目标,即应该以某种方式处理关联的可传输的组件。因此,如果您为每个组件的 TransferHandler 配置了特定的表,则支持的组件将始终是同一个表实例,并且您的检查将很简单。

如果您想根据发送者启用/禁用放置,则必须在每次拖动的基础上提供它:拖动从exportAsDrag开始并以exportDone结束,因此您可以在其中设置/取消发送者。

@Override
protected void exportDone(JComponent component,
Transferable transferable, int action) {
table = null;
}

@Override
public void exportAsDrag(JComponent comp, InputEvent e, int action) {
table = (JTable) comp;
super.exportAsDrag(comp, e, action);
}

现在您可以在表的多个实例中重复使用处理程序的同一实例:

TableTransferHandler handler = new TableTransferHandler();
tableA.setTransferHandler(handler);
tableB.setTransferHandler(handler);

顺便说一句:我不会摆弄光标,它们被支持在 dnd 子系统的完全控制之下。

关于java - 如何禁止两个 JTable 之间的拖放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21659357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com