使用移动列表处理拖放

时间:2014-07-27 12:56:40

标签: java swing drag-and-drop

我正在使用拖放功能。用户必须将某些内容从列表拖到其他位置。但是,列表会在收到ListSelectionEvent时移动,因此当用户更改选择时,他可能会意外地执行拖放操作

我的代码:

import java.awt.*;
import javax.swing.*;

class Main {
    public static void createGUI() {
        JFrame f = new JFrame();

        JList<String> list = new JList<>(new String[] { "Text A", "Text B" });
        list.setFont(list.getFont().deriveFont(24f));
        list.setDragEnabled(true);
        // list.setTransferHandler(new TransferHandler() { /* ... */ });
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.addListSelectionListener(e -> f.setLocation(f.getX(),
                f.getY() + f.getHeight()));
        list.setSelectedIndex(0);

        f.add(list, BorderLayout.CENTER);
        f.pack();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationByPlatform(true);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Main::createGUI);
    }
}

要重现,请启动此应用程序,将其置于某个接受放置的应用程序(例如Eclipse,Notepad ++)之上,并多次切换选择。

我使用的是Windows 7和JDK 1.8.0_5。

我试过但我无法找到解决办法。 如何解决此问题?


[不相关]这是我的真实应用:(包括绿色十字图标)

Screenshot (Empty) Screenshot (TopCoder)

2 个答案:

答案 0 :(得分:1)

好的,我想我理解你的问题:你想要启用DnD,而不是当用户改变他们的选择时。你应该尝试这个(在Java 7中,我对lambda表达式还不太熟悉,所以我还没有使用Java 8.虽然它可以在Java 8上运行):

class Main {
    private static boolean listChanging = false;

    public static void createGUI() {
        final JFrame f = new JFrame();
        JList<String> list = new JList<String>(new String[] { "Text A", "Text B" });
        list.setFont(list.getFont().deriveFont(24f));
        list.setDragEnabled(true);
        list.setTransferHandler(new TransferHandler() {
            private static final long serialVersionUID = 1L;

            @Override
            public int getSourceActions(JComponent c) {
                if (listChanging) {
                    listChanging = false;
                    return NONE;
                } else {
                    return COPY;
                }
            }

            @Override
            @SuppressWarnings("unchecked")
            public Transferable createTransferable(JComponent c) {
                return new StringSelection(((JList<String>) c).getSelectedValue());
            }
        });
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                f.setLocation(f.getX(), f.getY() + f.getHeight());
                listChanging = true;
            }
        });
        list.setSelectedIndex(0);
        f.add(list, BorderLayout.CENTER);
        f.pack();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationByPlatform(true);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Main.createGUI();
            }
        });
    }
}

此代码的作用是当用户更改选择时,将变量listChanging设置为true。当用户拖动(偶然或故意)时,它会检查listChanging是否为true,这意味着这可能是意外拖累。如果列表没有变化,那么它允许COPY拖动。

基本上,如果在列表更改期间拖动,则会禁用DnD。如果列表没有改变,并且用户有目的地拖动它就启用DnD。

希望这能满足您的所有需求:)

答案 1 :(得分:0)

仍然不清楚你想用你的应用程序做什么.. 拖放可以使用鼠标/键事件执行,也可以通过其他事件触发。 在我看来,可以通过这种方式从List中选择一些组件并执行DnD将该组件传输到另一个Container。

请详细说明您的问题,并具体询问您希望如何使用示例应用程序执行此操作。