拖动光标未显示在OSX上

时间:2016-05-18 20:32:29

标签: java macos drag-and-drop cursor

我们有一个在Windows和OSX上都使用的大型Java应用程序。 我们在两个JTable之间进行自定义拖放。

在Windows上,这非常有效。在目标JTable上拖动时会显示自定义光标。

在Mac上,永远不会显示自定义光标。而是在开始拖动时显示灰色矩形(仅限边框)。此矩形是表列的宽度和表的高度。我们的日志记录显示正在调用dragOver()和dropActionChanged()方法,我们正在设置自定义光标。它永远不会被显示出来。

如果我禁用自定义光标代码,则会显示相同的框 - 但它的中间也有圆圈/斜线图标。

我想摆脱怪异的盒子,并显示自定义光标。

摘自代码:

    private class FileTransferHandler extends TransferHandler {

    private static final long           serialVersionUID        = 1L;
    private final Logger                log             = LogManager.getLogger();
    private final CursorDragSourceListener  dragSourceListener  = new CursorDragSourceListener();

    // Left out the Drop handling code that was here

    @Override
    public int getSourceActions( final JComponent c) {
        log.debug("FileTransferHandler.getSourceAction: ");
        return COPY | MOVE;
    }

    @Override
    protected Transferable createTransferable( final JComponent c) {
        log.debug("FileTransferHandler.createTransferable:");
        List<iFilePage> pages = new ArrayList<iFilePage>();

        // Left out the code that builds the pages list

        DragSource.getDefaultDragSource().addDragSourceListener(dragSourceListener);
        dragSourceListener.setCursorChoice(pages.size() == 1);

        return new FilePageTransferable(pages);
    }

    @Override
    protected void exportDone(  final JComponent c,
                        final Transferable t,
                        final int action) {
        log.debug("FileTransferHandler.exportDone: {}", action, t);
        tblFixed.getSelectionModel().clearSelection();
        DragSource.getDefaultDragSource().removeDragSourceListener(dragSourceListener);
        return;
    }
}

private static class CursorDragSourceListener implements DragSourceListener {
    private Cursor  singlePage      = null;
    private Cursor  multiPage       = null;
    private Cursor  badSinglePage   = null;
    private Cursor  useCursor       = null;
    private boolean useSingle       = false;

    public CursorDragSourceListener() {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        URL url;
        String name;
        Image img;

        url = FileUtils.getResourceURL("/images/page.png");
        name = "DragPage";
        img = toolkit.createImage(url);
        singlePage = toolkit.createCustomCursor(img, new Point(16, 16), name);

        url = FileUtils.getResourceURL("/images/badpage_stack.png");
        name = "DragBadPage";
        img = toolkit.createImage(url);
        badSinglePage = toolkit.createCustomCursor(img, new Point(16, 16), name);

        url = FileUtils.getResourceURL("/images/page_stack.png");
        name = "DragPageStack";
        img = toolkit.createImage(url);
        multiPage = toolkit.createCustomCursor(img, new Point(16, 16), name);

        return;
    }

    public void setCursorChoice( final boolean single) {
        log.debug("CursorDragSourceListener.setCursorChoice: {}", single);
        useSingle = single;
        if (useSingle) {
            useCursor = singlePage;
        } else {
            useCursor = multiPage;
        }
        return;
    }

    @Override
    public void dropActionChanged( final DragSourceDragEvent dsde) {
        log.debug("CursorDragSourceListener.dropActionChanged: {}", dsde.getDropAction(), useSingle);

        if (dsde.getDropAction() == 2) {
            if (!useSingle) {
                useCursor = badSinglePage;
            } else {
                useCursor = singlePage;
            }

        } else {
            if (useSingle) {
                useCursor = singlePage;
            } else {
                useCursor = multiPage;
            }
        }

        dsde.getDragSourceContext().setCursor(useCursor);
        return;
    }

    @Override
    public void dragOver( final DragSourceDragEvent dsde) {

        try {
            Object x = dsde.getDragSourceContext().getTransferable()
                        .getTransferData(DataFlavor.javaFileListFlavor);
            log.trace("CursorDragSourceListener.dragOver: {}", (x != null) ? x.getClass().getSimpleName() : "null");

            if (x instanceof ArrayList) {
                dsde.getDragSourceContext().setCursor(useCursor);
            }

        } catch (Exception e) {
            log.error("CursorDragSourceListener.dragOver:", e);
        }
    }

    @Override
    public void dragExit( final DragSourceEvent dse) {
    }

    @Override
    public void dragEnter( final DragSourceDragEvent dsde) {
    }

    @Override
    public void dragDropEnd( final DragSourceDropEvent dsde) {
    }

}

1 个答案:

答案 0 :(得分:0)

经过多次检查和分析后,我们的自定义选择模型在OSX上引发了这个问题。 我们有一个选择模型,允许您选择多个单独的单元格,而不仅仅是整行。 因此getMinSelectionindex()和getMaxSelectionIndex()方法返回虚拟数据,因为我们从未使用它们。

在MS Win上运行正常,但显然JTable的OSX拖放使用了这些调用。

修改我们的代码以返回合理的值后,选择框不再像表那样高。

自定义光标大多数时间都会出现,但仍无条件地随机消失。

相关问题