我正在使用拖放功能。用户必须将某些内容从列表拖到其他位置。但是,列表会在收到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。
我试过但我无法找到解决办法。 如何解决此问题?
[不相关]这是我的真实应用:(包括绿色十字图标)
答案 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。
请详细说明您的问题,并具体询问您希望如何使用示例应用程序执行此操作。