【问题标题】:How to drag and drop a JLabel into a JPanel如何将 JLabel 拖放到 JPanel 中
【发布时间】:2018-10-06 09:49:16
【问题描述】:

在研究了如何使用Label DnD 之后,我发现使用了这个解决方案:

 public class LayerItem extends JLabel {
    int x = 0, y = 0;

    public LayerItem(String text) {
        this.setText(text);
        this.addMouseMotionListener(new MouseAdapter(){
            @Override
            public void mouseDragged(MouseEvent evt){
                lblMouseDragged(evt);
            }
        });
    }

    protected void lblMouseDragged(MouseEvent evt){
        this.x = evt.getX();
        this.y = evt.getY();
    }
}

当用户单击并按住 JLabel 时,X 和 Y 会随着鼠标的移动而记录下来。但是,我不知道如何知道点击何时停止(即用户到达他的目标 JPanel)然后将文本移入其中。

允许 JPanel 接收放置操作的唯一参考是通过执行以下操作:

new JPanel().setDropTarget(getDropTarget());

但是,我再也找不到任何关于通过 JLabel 作为带有坐标(绝对布局)的放置目标的参考。

【问题讨论】:

标签: java swing drag-and-drop


【解决方案1】:

查看@MadProgrammer 发布的几个示例后,我想出了一个扩展 JPanel 和 JLabel 的解决方案。这是 JLabel 类:

public class LayerItem extends JLabel {

    public LayerItem(String text) {

        this.setText(text);

        this.setTransferHandler(new ValueExportTransferHandler(text));

        this.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                JLabel lbl = (JLabel) e.getSource();
                TransferHandler handle = lbl.getTransferHandler();
                handle.exportAsDrag(lbl, e, TransferHandler.COPY);
            }
        });

    }

    protected static class ValueExportTransferHandler extends TransferHandler {

        public static final DataFlavor SUPPORTED_DATE_FLAVOR = DataFlavor.stringFlavor;
        private String value;

        public ValueExportTransferHandler(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        @Override
        public int getSourceActions(JComponent c) {
            return DnDConstants.ACTION_COPY_OR_MOVE;
        }

        @Override
        protected Transferable createTransferable(JComponent c) {
            Transferable t = new StringSelection(getValue());
            return t;
        }

        @Override
        protected void exportDone(JComponent source, Transferable data, int action) {
            super.exportDone(source, data, action);
            // Clean up and remove the LayerItem that was moved
            ((LayerItem) source).setVisible(false);
            ((LayerItem) source).getParent().remove((LayerItem) source);
        }

    }
}

这是 JPanel 的类:

public class LayerContainer extends JPanel {

    public LayerContainer() {
        this.setTransferHandler(new ValueImportTransferHandler());
        this.setLayout(new GridBagLayout()); // Optional layout
        this.setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY), new EmptyBorder(20, 20, 20, 20))); // Optional border
    }

    protected static class ValueImportTransferHandler extends TransferHandler {

        public static final DataFlavor SUPPORTED_DATE_FLAVOR = DataFlavor.stringFlavor;

        public ValueImportTransferHandler() {
        }

        @Override
        public boolean canImport(TransferHandler.TransferSupport support) {
            return support.isDataFlavorSupported(SUPPORTED_DATE_FLAVOR);
        }

        @Override
        public boolean importData(TransferHandler.TransferSupport support) {
            boolean accept = false;
            if (canImport(support)) {
                try {
                    Transferable t = support.getTransferable();
                    Object value = t.getTransferData(SUPPORTED_DATE_FLAVOR);
                    if (value instanceof String) { // Ensure no errors
                        // TODO: here you can create your own handler
                        // ie: ((LayerContainer) component).getHandler()....
                        Component component = support.getComponent();
                        LayerItem j = new LayerItem((String) value);
                        ((LayerContainer) component).add(j); // Add a new drag JLabel
                        accept = true;
                    }
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }
            return accept;
        }
    }

}

这是一个如何使用它的示例(从一个 JPanel 拖到另一个并再次返回):

    JPanel left_panel = new LayerContainer();
    panel_1.setBounds(28, 47, 129, 97);
    add(panel_1);

    LayerContainer right_panel = new LayerContainer();
    layerContainer.setBounds(203, 47, 129, 97);
    add(layerContainer);

    JLabel lblToDrag = new LayerItem("Drag Me");
    GridBagConstraints gbc_lblToDrag = new GridBagConstraints();
    gbc_lblDragMe.gridx = 0;
    gbc_lblDragMe.gridy = 0;
    panel_right.add(lblToDrag, gbc_lblToDrag);

为了将来的使用,我将创建一个 onTransfer() 方法并创建我自己的 LayerContainerHandler() 覆盖 run() 方法,因此每次将标签移动到不同的容器时,它都会执行单独的操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    相关资源
    最近更新 更多