在 Java 中从 JButton 拖放到 JComponent

Posted

技术标签:

【中文标题】在 Java 中从 JButton 拖放到 JComponent【英文标题】:Drag and Drop from JButton to JComponent in Java 【发布时间】:2015-05-04 20:35:35 【问题描述】:

我在互联网上搜索了如何将 JButtons 拖放到对象的示例,但我无法使其工作。

我的程序所做的是,当我单击一个按钮时,对象会更新一个字段(使用 selectedobject.setField())。我希望能够做到这一点不是通过单击,而是通过拖动 JButton。

我该怎么做? 我找到了这个,并尝试输入我的代码:

btn.setTransferHandler(new ImageHandler());
btn.addMouseListener(new MouseAdapter() 
    public void mousePressed(MouseEvent e) 
        JComponent c = (JComponent)e.getSource();
        TransferHandler handler = c.getTransferHandler();
        handler.exportAsDrag(c, e, TransferHandler.COPY);
    
);

我从 here 获取了 ImageHandler 类。

【问题讨论】:

“获得新价值”是什么意思?你想把按钮的“值”拖到别的东西上吗? 按钮为选中的对象添加动画。我希望能够通过拖放将相同的动画添加到随机对象。 【参考方案1】:

Drag'n'drop 是一袋有趣的松脆胡萝卜……没有“核心”API 和更新的“转移”API 的帮助,所以很容易混淆

以下示例使用“传输”API,基本上将 String 值从按钮传输到 JLabel

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                try 
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                 catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) 
                    ex.printStackTrace();
                

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public class TestPane extends JPanel 

        public TestPane() 
            setLayout(new GridLayout(1, 2));
            add(createLeftPanel());
            add(createRightPanel());

        

        protected JPanel createLeftPanel() 
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.weightx = 1;
            for (int index = 0; index < 10; index++) 
                JButton btn = new JButton(Integer.toString(index + 1));
                panel.add(btn, gbc);
                btn.setTransferHandler(new ValueExportTransferHandler(Integer.toString(index + 1)));

                btn.addMouseMotionListener(new MouseAdapter() 
                    @Override
                    public void mouseDragged(MouseEvent e) 
                        JButton button = (JButton) e.getSource();
                        TransferHandler handle = button.getTransferHandler();
                        handle.exportAsDrag(button, e, TransferHandler.COPY);
                    
                );
            
            return panel;
        

        protected JPanel createRightPanel() 
            JPanel panel = new JPanel(new GridBagLayout());
            JLabel label = new JLabel("Drop in");
            label.setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY), new EmptyBorder(20, 20, 20, 20)));
            label.setTransferHandler(new ValueImportTransferHandler());
            panel.add(label);
            return panel;
        

    

    public 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);
            // Decide what to do after the drop has been accepted
        

    

    public 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) 
                        Component component = support.getComponent();
                        if (component instanceof JLabel) 
                            ((JLabel) component).setText(value.toString());
                            accept = true;
                        
                    
                 catch (Exception exp) 
                    exp.printStackTrace();
                
            
            return accept;
        
    

我已经尽力将TransferHandlers 分开,允许“拖放”版本。您不必“必须”执行此操作,您“可以”使用单个 TransferHandler 来执行这两个操作,这取决于您。

您必须修改ValueExportTransferHandler 以接受不同的值并相应地修改SUPPORTED_DATE_FLAVOR,但这些是基础

你也可以看看Drag and Drop custom object from JList into JLabel作为另一个例子......

【讨论】:

那里出了点问题。我的意思是,不应该为每一个拖动事件调用“exportAsDrag”,对吗?即使它可能在实践中起作用。编辑:我刚刚运行它。它可以工作,并且由于某种原因,mouseDragged 方法只执行了一次,所以一切似乎都很好。 @DreamspacePresident 为什么不呢? exportAsDragmouseDragged 上被调用,如果没有,那么应该什么时候调用? ps-我想你在想mouseMoved ;) 因为 exportAsDrag 的文档说“导致启动 Swing 拖动支持。”和“在此呼叫返回时,传输不一定已完成(即呼叫不会阻塞等待丢弃)。”对我来说,这清楚地暗示了这个东西将在每个 D&D 中被称为 一次。但是看看我对我的其他评论的编辑,一切似乎都很好。

以上是关于在 Java 中从 JButton 拖放到 JComponent的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中从 TableView 拖放到另一个视图

JAVA SAP JCO3.0 抛出这个异常:java.lang.UnsatisfiedLinkError: no sapjco3 in java.library.path

JAVA SAP JCO3.0 抛出这个异常:java.lang.UnsatisfiedLinkError: no sapjco3 in java.library.path

将文件路径拖放到 Java Swing JTextField

SAP R3和JAVA交换数据之JCO

调用JCO连接SAP的问题