Enable stringFlavor of Transfersupport in Java Swing

前端 未结 2 547
南旧
南旧 2020-12-19 16:38

I am implementing a functionality to Drag and Drop the Textattribute of JLabels into the cells of a JTable. So I\'ve created a custom TransferHandler for the table. But eve

相关标签:
2条回答
  • 2020-12-19 17:04

    An higher-level alternative to David's low-level approach (for the drag off the label), is to use the in-build property transfer on it. It's installed by simply setting the transferHandler and a mouseListener which triggers the export:

    MouseListener listener = new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
            JComponent c = (JComponent) e.getSource();
            TransferHandler handler = c.getTransferHandler();
            handler.exportAsDrag(c, e, TransferHandler.COPY);
        }
    };
    // a transferHandler configured to export the text property
    TransferHandler handler = new TransferHandler("text");
    JComponent labels = new JPanel();
    for (int i = 0; i < 4; i++) {
        JLabel label1 = new JLabel("item: " + i);
        label1.addMouseListener(listener);
        label1.setTransferHandler(handler);
        labels.add(label1);
    }
    

    The price to pay is slightly more work in the TableTransferHandler: it now has to check not only against the pre-defined stringFlavor but check the representationClass against String and accept that as well:

    public class TableHandlerExt extends TransferHandler {
    
        /**
         * Implemented to return true if the support can provide string values.
         */
        @Override
        public boolean canImport(TransferSupport support) {
            if (!support.isDrop()) {
                return false;
            }
            return isStringDataSupported(support);
        }
    
        /**
         * Returns a boolean indicating whether or not the support can
         * provide a string value. Checks for predefined DataFlavor.stringFlavor
         * and flavors with a representationClass of String.
         */
        protected boolean isStringDataSupported(TransferSupport support) {
            if (support.isDataFlavorSupported(DataFlavor.stringFlavor)) return true;
            DataFlavor[] flavors = support.getDataFlavors();
            for (DataFlavor dataFlavor : flavors) {
                if (dataFlavor.getRepresentationClass() == String.class) return true;
            }
            return false;
        }
    
        @Override
        public boolean importData(TransferSupport support) {
            if (!canImport(support)) {
                return false;
            }
    
            String line;
            try {
                line = getStringData(support);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
    
            JTable table = (JTable) support.getComponent();
            JTable.DropLocation dl = (JTable.DropLocation) support.getDropLocation();
            int column = dl.getColumn();
            int row = dl.getRow();
    
            if (!line.isEmpty()) {
                // note: we need to use table api to access the table, as the 
                // row/column coordinates are view coordinates
                table.setValueAt(line, row, column);
            }
            return true;
        }
    
        /**
         * Returns the String provided by the support. 
         * Tries for predefined DataFlavor.stringFlavor
         * and flavors with a representationClass of String.            
         */
        protected String getStringData(TransferSupport support) 
            throws UnsupportedFlavorException, IOException {
            if (support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                return (String) support.getTransferable().getTransferData(DataFlavor.stringFlavor);
            }
            DataFlavor[] flavors = support.getDataFlavors();
            for (DataFlavor dataFlavor : flavors) {
                if (dataFlavor.getRepresentationClass() == String.class) {
                    return (String) support.getTransferable().getTransferData(dataFlavor);
                }
            }
            return "";
        }
    
    }
    
    0 讨论(0)
  • 2020-12-19 17:07

    Check this example seems to work fine:

    Before any dragging / dropping of JLabels:

    enter image description here

    Clicked and dragged Hello JLabel to 1st cell:

    enter image description here

    On release of click over the first cell:

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.datatransfer.DataFlavor;
    import java.awt.datatransfer.Transferable;
    import java.awt.datatransfer.UnsupportedFlavorException;
    import java.awt.dnd.DnDConstants;
    import java.awt.dnd.DragGestureEvent;
    import java.awt.dnd.DragGestureListener;
    import java.awt.dnd.DragSource;
    import java.io.IOException;
    import javax.swing.DropMode;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.SwingUtilities;
    import javax.swing.TransferHandler;
    
    public class Test {
    
        public static void main(String[] args) {
            createAndShowJFrame();
        }
    
        public static void createAndShowJFrame() {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
    
                    JFrame frame = createJFrame();
                    frame.setVisible(true);
    
                }
            });
        }
    
        private static JFrame createJFrame() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.setTitle("Test");
    
            JTable table = createJTable();
            JScrollPane js = new JScrollPane(table);
    
            frame.add(js, BorderLayout.CENTER);
    
            frame.add(createJLabelPanel(), BorderLayout.SOUTH);
    
            frame.pack();
    
            //frame.setResizable(false);//make it un-resizeable
            //frame.setLocationRelativeTo(null);//center JFrame
    
            return frame;
        }
    
        private static JTable createJTable() {
            // setup table data
            String[] columns = new String[]{"Foo", "Bar", "Baz", "Quux"};
            String[][] data = new String[][]{{"A", "B", "C", "D"},
                {"1", "2", "3", "4"},
                {"i", "ii", "iii", "iv"}};
            // create table
            final JTable table = new JTable(data, columns);
    
            // set up drag and drop
            table.setDragEnabled(true);
            table.setDropMode(DropMode.USE_SELECTION);
            table.setFillsViewportHeight(true);
    
            TransferHandler dnd = new TransferHandler() {
                @Override
                public boolean canImport(TransferSupport support) {
                    if (!support.isDrop()) {
                        return false;
                    }
                    //only Strings
                    if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                        return false;
                    }
                    return true;
                }
    
                @Override
                public boolean importData(TransferSupport support) {
                    if (!canImport(support)) {
                        return false;
                    }
    
                    Transferable tansferable = support.getTransferable();
                    String line;
                    try {
                        line = (String) tansferable.getTransferData(DataFlavor.stringFlavor);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return false;
                    }
    
                    JTable.DropLocation dl = (JTable.DropLocation) support.getDropLocation();
                    int column = dl.getColumn();
                    int row = dl.getRow();
    
                    String[] data = line.split(",");
                    for (String item : data) {
                        if (!item.isEmpty()) {
                            table.getModel().setValueAt(item, row, column);
                        }
                    }
                    return true;
                }
            };
            table.setTransferHandler(dnd);
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            return table;
        }
    
        private static JPanel createJLabelPanel() {
            JPanel panel = new JPanel();
            JLabel label1 = new JLabel("Hello");
            JLabel label2 = new JLabel("Yay");
            JLabel label3 = new JLabel("Bye");
    
            MyDragGestureListener dlistener = new MyDragGestureListener();
            DragSource ds1 = new DragSource();
            ds1.createDefaultDragGestureRecognizer(label1, DnDConstants.ACTION_COPY, dlistener);
    
            DragSource ds2 = new DragSource();
            ds2.createDefaultDragGestureRecognizer(label2, DnDConstants.ACTION_COPY, dlistener);
    
            DragSource ds3 = new DragSource();
            ds3.createDefaultDragGestureRecognizer(label3, DnDConstants.ACTION_COPY, dlistener);
    
            panel.add(label1);
            panel.add(label2);
            panel.add(label3);
            return panel;
        }
    }
    
    class MyDragGestureListener implements DragGestureListener {
    
        @Override
        public void dragGestureRecognized(DragGestureEvent event) {
            JLabel label = (JLabel) event.getComponent();
            final String text = label.getText();
    
    
            Transferable transferable = new Transferable() {
                @Override
                public DataFlavor[] getTransferDataFlavors() {
                    return new DataFlavor[]{DataFlavor.stringFlavor};
                }
    
                @Override
                public boolean isDataFlavorSupported(DataFlavor flavor) {
                    if (!isDataFlavorSupported(flavor)) {
                        return false;
                    }
                    return true;
                }
    
                @Override
                public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
                    return text;
                }
            };
            event.startDrag(null, transferable);
        }
    }
    
    0 讨论(0)
提交回复
热议问题