Я заметил, что использование setDragImage из поддержки перетаскивания JList работает в Windows 10 Professional x86, тогда как в Arch Linux 4.17.5 с XFCE это не так.
Видимая разница:


Сначала я подозревал, что это может быть проблема из-за разных версий JDK: Oracle JDK в Windows и OpenJDK в Linux, обе версии 1.8.0_172.
Но те же результаты я получил после перехода на Oracle JDK 1.8.0_172 в Arch Linux.
Во время отладки с помощью IntelliJ в Linux я мог видеть, что изображение перетаскивания создается просто как BufferedImage из элемента JList, но вызов setDragImage, похоже, не оказывает никакого влияния на Linux.
Следующий код для воспроизведения этой проблемы является измененной версией Ответ Атераи здесь:
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.image.BufferedImage;
import java.util.List;
// From https://stackoverflow.com/questions/11437402/setdragimage-not-working-java-7#11448623
public class BasicDnd {
private static void createAndShowGUI() {
JFrame f = new JFrame("BasicDnD");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(new BasicDnd().makeUI());
f.setSize(320, 320);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
printJavaInfo();
EventQueue.invokeLater(BasicDnd::createAndShowGUI);
}
private static void printJavaInfo() {
Package runtimePackage = Runtime.class.getPackage();
String specVendor = runtimePackage.getSpecificationVendor();
String implementationVendor = runtimePackage.getImplementationVendor();
String version = runtimePackage.getImplementationVersion();
System.out.println("Specification vendor: " + specVendor);
System.out.println("Implementation vendor: " + implementationVendor);
System.out.println("JRE version: " + version);
}
private JList makeList() {
DefaultListModel<String> m = new DefaultListModel<>();
m.addElement("Martha Washington");
m.addElement("Abigail Adams");
m.addElement("Martha Randolph");
JList<String> list = new JList<>(m);
list.setTransferHandler(new TransferHandler() {
private final JPanel p = new JPanel();
private BufferedImage bufferedImage;
private int width, height;
@Override
public boolean canImport(TransferHandler.TransferSupport info) {
if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
return false;
}
JList.DropLocation dl = (JList.DropLocation) info.getDropLocation();
return dl.getIndex() != -1;
}
@Override
public int getSourceActions(JComponent c) {
BufferedImage img = makeImageFromString(c);
if (img != null) {
setDragImage(img);
}
return COPY;
}
private BufferedImage makeImageFromString(JComponent src) {
JList l = (JList) src;
int idx = l.getSelectedIndex();
Rectangle rect = list.getCellBounds(idx, idx);
if (rect == null) return null;
if (bufferedImage == null || rect.width != width || rect.height != height) {
width = rect.width;
height = rect.height;
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}
Component c = l.getCellRenderer().getListCellRendererComponent(
l, l.getSelectedValue(), idx, false, false);
Graphics g = bufferedImage.getGraphics();
g.clearRect(0, 0, width, height);
SwingUtilities.paintComponent(g, c, p, 0, 0, width, height);
g.dispose();
return bufferedImage;
}
@Override
protected Transferable createTransferable(JComponent c) {
JList list = (JList) c;
List values = list.getSelectedValuesList();
StringBuilder buff = new StringBuilder();
for (int i = 0; i < values.size(); i++) {
Object val = values.get(i);
buff.append(val == null ? "" : val.toString());
if (i != values.size() - 1) {
buff.append("\n");
}
}
return new StringSelection(buff.toString());
}
});
list.setDropMode(DropMode.ON_OR_INSERT);
list.setDragEnabled(true);
return list;
}
private JComponent makeUI() {
JPanel panel = new JPanel(new GridLayout(2, 1));
JTextArea textArea = new JTextArea("Drag here from JList!");
panel.add(new JScrollPane(textArea));
panel.add(new JScrollPane(makeList()));
return panel;
}
}
Как мне получить перетаскиваемое изображение в Linux?
Спасибо VGR, в Linux isDragImageSupported возвращает false, а в Windows - true. Похоже, в Linux нет возможности получить перетаскиваемое изображение.




Что возвращает DragSource.isDragImageSupported ()?