摆动拖动图像在Linux上不起作用

时间:2018-07-17 12:36:21

标签: java linux swing drag-and-drop

我注意到从JList的拖放支持中使用setDragImage在Windows 10 Professional x86上有效,而在带有XFCE的Arch Linux 4.17.5上则无效。

可见差异:

在Windows上拖动图像

Drag and Drop on Window

在Linux上没有拖动图像

Drag and Drop on Linux

起初,我怀疑这可能是由于JDK版本不同而引起的:Windows上的Oracle JDK和Linux上的OpenJDK(版本1.8.0_172)。

但是切换到Oracle JDK 1.8.0_172 on Arch Linux后,我得到了相同的结果。

在Linux上使用IntelliJ进行调试时,我可以看到从BufferedImage的元素创建的拖拽图像恰好是JList,但对setDragImage的调用却没有似乎对Linux有任何影响。

以下重现此问题的代码是aterai's answer here的修改版本:

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上获取拖动图像?

0 个答案:

没有答案