是否可以使用 java Swing DnD api 在 mousePressed 上开始拖动? [英] Is it possible to start drag on mousePressed using java Swing DnD api?

查看:42
本文介绍了是否可以使用 java Swing DnD api 在 mousePressed 上开始拖动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的示例中,有一种标准的拖放触发方式,即mousePress+mouseMove.

In the example below there is a standard way to trigger drag and drop, which is mousePress+mouseMove.

import javax.swing.*;
import java.awt.datatransfer.StringSelection;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;

public class DndExample extends JFrame  {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new DndExample());
    }

    public DndExample() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel dragLabel = createDndLabel();
        getContentPane().add(dragLabel);
        pack();
        setVisible(true);
    }

    private JLabel createDndLabel() {
        JLabel label = new JLabel("Drag me, please");


        DragGestureListener dragGestureListener = (dragTrigger) -> {
            dragTrigger.startDrag(null, new StringSelection(label.getText()));
        };

        DragSource dragSource = DragSource.getDefaultDragSource();
        dragSource.createDefaultDragGestureRecognizer(label, DnDConstants.ACTION_COPY, dragGestureListener);

        return label;
    }
}

是否可以在没有 mouseMove 的情况下在 mousePressed 上触发 startDrag?所需的行为是这样的:我按下鼠标按钮,然后光标发生变化,表明拖动已经开始,如果移动鼠标而不是继续拖动.我显然知道我可以添加 MouseListener 并手动更改光标,但需要更多代码来恢复以前的光标.

Is it possible to trigger startDrag on mousePressed without mouseMove? The desired behaviour is something like that: I press the mouse button then cursor changes indicating that drag has started, if mouse is moved than drag is continued. I obviously know that I may add MouseListener and change cursor manually but there is much more code needed to restore previous cursor.

推荐答案

因为你要求的是非标准的行为,所以你需要自己做额外"的提升,这需要你有一个 MouseListenermousePressed 设置光标和 mouseReleased 休息它(所以如果用户只是点击而不拖动组件,你不会结束一个愚蠢的光标状态)和 DragGestureListener#dragDropEnd 也重置光标.

Because you're asking for non-standard behaviour, you're going to need to do the "extra" lifting yourself, this requires you to have a MouseListener with mousePressed setting the cursor and mouseReleased resting it (so if the user just clicks and doesn't drag the component, you don't end up with a stupid cursor state) and the DragGestureListener#dragDropEnd also resetting the cursor.

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
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.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;

public class DragAndDropTest {

    public static void main(String[] args) {
        new DragAndDropTest();
    }

    public DragAndDropTest() {
        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(new DropPane());
            add(new DragPane());
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class DragPane extends JPanel {

        private DragSource ds;
        private Transferable transferable;

        public DragPane() {
            addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    setCursor(Cursor.getDefaultCursor());
                }
            });
            ds = new DragSource();
            transferable = new Transferable() {

                @Override
                public DataFlavor[] getTransferDataFlavors() {
                    return new DataFlavor[]{DataFlavor.stringFlavor};
                }

                @Override
                public boolean isDataFlavorSupported(DataFlavor flavor) {
                    return DataFlavor.stringFlavor.equals(flavor);
                }

                @Override
                public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
                    return "This is a test";
                }
            };
            ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, new DragGestureListener() {
                @Override
                public void dragGestureRecognized(DragGestureEvent dge) {
                    // This is where you would export the data you want
                    // to transfer
                    ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.HAND_CURSOR), transferable, new DragSourceListener() {

                        @Override
                        public void dragEnter(DragSourceDragEvent dsde) {
                        }

                        @Override
                        public void dragOver(DragSourceDragEvent dsde) {
                        }

                        @Override
                        public void dropActionChanged(DragSourceDragEvent dsde) {
                        }

                        @Override
                        public void dragExit(DragSourceEvent dse) {
                        }

                        @Override
                        public void dragDropEnd(DragSourceDropEvent dsde) {
                            setCursor(Cursor.getDefaultCursor());
                        }

                    });
                }
            });

            setLayout(new GridBagLayout());
            add(new JLabel("Drag from here"));
            setBorder(new LineBorder(Color.RED));
        }

    }

    public class DropPane extends JPanel {

        private List<Point> dropPoints;

        public DropPane() {
            dropPoints = new ArrayList<>(25);
            setDropTarget(new DropTarget(this, new DropTargetListener() {

                @Override
                public void dragEnter(DropTargetDragEvent dtde) {
                }

                @Override
                public void dragOver(DropTargetDragEvent dtde) {
                }

                @Override
                public void dropActionChanged(DropTargetDragEvent dtde) {
                }

                @Override
                public void dragExit(DropTargetEvent dte) {
                }

                @Override
                public void drop(DropTargetDropEvent dtde) {
                    // Normally here, I'd inspect the Transferable and make sure
                    // what is been dropped and can be imported, I'd then go through
                    // the process of unwrapping the data from the Transferable and 
                    // processing it appropriatly, but in this example, I really don't
                    // care, I just care about WHERE the event occured
                    dropPoints.add(dtde.getLocation());
                    dtde.dropComplete(true);
                    repaint();
                }
            }));
            setLayout(new GridBagLayout());
            add(new JLabel("Drop to here"));
            setBorder(new MatteBorder(1, 1, 1, 0, Color.RED));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            for (Point p : dropPoints) {
                g.fillOval(p.x - 2, p.y - 2, 5, 5);
            }
        }

    }

}

现在,请记住,您正在做系统不希望您做的事情,因此它可能会转身并以任何方式字节您

Now, remember, you're doing something the system doesn't want you to do, so it might turn around and byte you any way

我可能会考虑编写一个工厂方法,它引用ComponentTransferable(可能还有一个Cursor)并构建和注册MouseListenerDragSource

I might consider writing a factory method which took a reference to Component, Transferable (and probably a Cursor) and build and registered the MouseListener and DragSource

这篇关于是否可以使用 java Swing DnD api 在 mousePressed 上开始拖动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆