在回转中的两个零部件之间拖动



我想我并没有试图拖放。我希望能够在Swing中将标记从一个图形组件拖动到相邻的图形组件。我现在遇到的问题是,当我按住拖动时,MouseEvent的源字段总是设置为拖动开始的组件。在鼠标输入和/或退出时,有没有办法让Swing停止在我拖动的组件上生成MouseEvents,并开始在我当前拖动的组件中生成MouseEvent?

几个Swing组件内置了对拖放的支持,这使得在许多用例中处理鼠标事件变得非常困难。

下面是一个在两个JList之间一次来回移动一个或多个字符串的示例。在后台,TransferHandler管理字符串的添加和删除。

以下示例基于此和此。

/**
 * The user can move list items between two lists using drag and drop
 * @author Matthias Braun
 *
 */
public class BidirectionalDragAndDrop extends JFrame {
    private static final long serialVersionUID = 1L;
    public BidirectionalDragAndDrop() {
        JList<String> source = createJListWithDragAndDrop();
        source.setModel(createSourceListModel());
        JList<String> target = createJListWithDragAndDrop();
        target.setModel(new DefaultListModel<String>());
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, source, target);
        JLabel label = new JLabel("You can drag the fruits from the left list to the right and vice versa");
        add(splitPane);
        add(label, BorderLayout.NORTH);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        pack();
        setVisible(true);
    }
    private JList<String> createJListWithDragAndDrop() {
        JList<String> list = new JList<>();
        list.setDragEnabled(true);
        list.setDropMode(DropMode.INSERT);
        StringMoveHandler.createFor(list);
        return list;
    }
    private static DefaultListModel<String> createSourceListModel() {
        DefaultListModel<String> listModel = new DefaultListModel<>();
        for (String str : Arrays.asList("Papaya", "Orange", "Apple", "Mango", "Pear", "Avocado")) {
            listModel.addElement(str);
        }
        return listModel;
    }
    /**
     * Handles the moving of one or multiple strings between {@link JList}s.
     * 
     * @author Matthias Braun
     *
     */
    private static class StringMoveHandler extends TransferHandler {
        private static final long serialVersionUID = 1L;
        private DataFlavor objectArrayFlavor = new ActivationDataFlavor(Object[].class, DataFlavor.javaJVMLocalObjectMimeType, "Array of items");
        // We'll be moving the strings of this list
        private JList<String> list;
        // Clients should use a static factory method to instantiate the handler
        private StringMoveHandler() {
        };
        public static StringMoveHandler createFor(JList<String> list) {
            StringMoveHandler handler = new StringMoveHandler();
            list.setTransferHandler(handler);
            handler.list = list;
            return handler;
        }
        @Override
        public boolean canImport(TransferSupport info) {
            return info.isDataFlavorSupported(objectArrayFlavor);
        }
        @Override
        public boolean importData(TransferSupport transferSupport) {
            Transferable t = transferSupport.getTransferable();
            boolean success = false;
            try {
                Object[] importedData = (Object[]) t.getTransferData(objectArrayFlavor);
                addToListModel(importedData);
                success = true;
            }
            catch (UnsupportedFlavorException | IOException e) {
                e.printStackTrace();
            }
            return success;
        }
        private void addToListModel(Object[] importedData) {
            JList.DropLocation loc = list.getDropLocation();
            int dropIndex = loc.getIndex();
            DefaultListModel<String> listModel = (DefaultListModel<String>) list.getModel();
            for (int i = 0; i < importedData.length; i++) {
                Object elem = importedData[i];
                if (elem instanceof String) {
                    listModel.add(dropIndex + i, (String) elem);
                }
                else {
                    System.err.println("Imported data contained something else than strings: " + elem);
                }
            }
        }
        @Override
        public int getSourceActions(JComponent c) {
            return TransferHandler.COPY_OR_MOVE;
        }
        @Override
        public Transferable createTransferable(JComponent source) {
            // We need the values from the list as an object array, otherwise the data flavor won't match in importData
            @SuppressWarnings("deprecation")
            Object[] valuesToTransfer = list.getSelectedValues();
            return new DataHandler(valuesToTransfer, objectArrayFlavor.getMimeType());
        }
        @Override
        protected void exportDone(JComponent source, Transferable data, int action) {
            if (action == TransferHandler.MOVE) {
                try {
                    Object[] exportedData = (Object[]) data.getTransferData(objectArrayFlavor);
                    removeFromListModel(exportedData);
                }
                catch (UnsupportedFlavorException | IOException e) {
                    e.printStackTrace();
                }
            }
        }
        private void removeFromListModel(Object[] dataToRemove) {
            DefaultListModel<String> listModel = (DefaultListModel<String>) list.getModel();
            for (Object elemToRemove : dataToRemove) {
                boolean removedSuccessfully = listModel.removeElement(elemToRemove);
                if (!removedSuccessfully) {
                    System.err.println("Source model did not contain exported data");
                }
            }
        }
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    new BidirectionalDragAndDrop();
                }
                catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

相关内容

  • 没有找到相关文章

最新更新