Изображение перетаскивания Swing не работает в Linux

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

Видимая разница:

Перетащите изображение в Windows

Изображение перетаскивания Swing не работает в Linux

Нет перетаскивания изображения в Linux

Изображение перетаскивания Swing не работает в Linux

Сначала я подозревал, что это может быть проблема из-за разных версий 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?

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

VGR 17.07.2018 16:10

Спасибо VGR, в Linux isDragImageSupported возвращает false, а в Windows - true. Похоже, в Linux нет возможности получить перетаскиваемое изображение.

Matthias Braun 17.07.2018 16:30
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
116
0

Другие вопросы по теме