【问题标题】:Drag Cursor not showing on OSX拖动光标未在 OSX 上显示
【发布时间】:2016-05-18 20:32:28
【问题描述】:

我们有一个可在 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) {
    }

}

【问题讨论】:

    标签: java macos drag-and-drop cursor


    【解决方案1】:

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

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

    修改我们的代码返回合理值后,选择框不再和表格一样高了。

    自定义光标大部分时间都会出现,但仍会无缘无故随机消失。

    【讨论】:

      猜你喜欢
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多