【问题标题】:Handling drag-and-drop with a moving list使用移动列表处理拖放
【发布时间】:2014-07-27 12:56:39
【问题描述】:

我正在使用拖放操作。用户必须将某些内容从列表中拖到其他地方。但是,当收到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。

我试过了,但找不到解决方法。 如何解决此问题?


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

【问题讨论】:

  • 测试您的代码后的最终用户想法:1) 我真的很讨厌以这种方式运行的应用程序。我的意思是,在选择事件上移动列表有什么意义?如果我使用 DnD,我希望组件保持安静,这样我就可以在视觉上仔细检查我正在拖动正确的列表项。 2) 正如您所指出的,移动列表很容易出现意外下降。 3) 我知道这只是一个示例,但在进行两次选择后,我的屏幕上不再显示该框架。
  • @dic19 加油!我对您的第一点和第三点进行了更新。
  • 那么,您不想在任何地方使用拖放效果,还是想修改它的放置位置? (另外,我想我发现了 DnD 使用中最奇怪的极端案例;)。)
  • @dudeprgm 它拖动时。
  • 只要确保我在这里给出正确答案:您想在用户拖动时收到通知,对吗? (如果你想完全禁用 DnD,只需使用 list.setTransferHandler(null),但我认为这不是你想要的。)

标签: java swing drag-and-drop


【解决方案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。

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

【讨论】:

  • 看起来很合理。我会在处理应用程序时尝试一下。
  • @johnchen902 好的,让我知道它是如何为你工作的,我可以更新/更改它。
  • 是的,它有效!列表并不总是移动的问题,但我通过检查时间解决了它。如果您有更好的建议,我将不胜感激!
  • 我当然会,但我想等到赏金结束。
【解决方案2】:

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

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

【讨论】:

  • 我想我的问题已经很清楚了:修复错误。并请详细说明您的答案。在当前状态下,它应该是一个评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
相关资源
最近更新 更多