如何通过拖放交换jtable中的单元格值

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)

Mad*_*mer 7

拖放不是一个简单的过程,它非常复杂且涉及到.这种复杂性带来了灵活性.

以这种方式交换值与"移动" 本身不同.当移动某些东西时,你从源头获取它并将它放在目标中,这里我们在源和目标之间交换值,这意味着我们需要比通常通过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)