我正在使用拖放操作。用户必须将列表中的某些内容拖到其他位置。但是,当接收到 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。
我尝试过,但找不到解决方法。 如何解决此问题?
<小时/>[不太相关]这是我真正的应用程序:(包括绿色十字图标)
最佳答案
好的,我想我理解您的问题:您希望启用 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。
希望这能满足您的所有需求:)
关于java - 使用移动列表处理拖放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24981186/