将自定义光标设置为在拖动外部文件进入Swing应用程序时的光标

7
我有一个swing应用程序,我想通过将外部文件从Windows资源管理器拖到应用程序中来导入外部文件。我已经实现了这个基本功能。但是,我想将默认的拖放光标图标变成适合应用程序的光标。我尝试过使用DragGestureListener和DragSource来完成这个任务,但却没有成功。如果拖放操作是在同一个swing应用程序内进行,则可以看到这种方法运行的示例。但是,当拖放源在Swing之外时,这些方法似乎不会被调用。在将外部文件拖入swing应用程序时,是否可能更改拖动光标?请参考以下简化示例:
public class DnDTemplate extends JFrame {

private static final long serialVersionUID = 1L;
private JComponent thePane = null;
private Cursor dropCursor = null;

public DnDTemplate() {
    super( "Drop File Here" );

    thePane = (JComponent) getContentPane();
    thePane.setTransferHandler( new DndTransferHandler() );

    ImageIcon imageIcon = new ImageIcon( "drop_here.gif" );
    Image image = imageIcon.getImage();     
    BufferedImage bufferedImage = new BufferedImage( 16, 16, BufferedImage.TYPE_INT_ARGB );
    Graphics graphics = bufferedImage.getGraphics();
    graphics.drawImage( image, 0, 0, null );
    dropCursor = Toolkit.getDefaultToolkit().createCustomCursor( bufferedImage, new Point( 16, 16 ), "drop cursor" );

    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    setSize( 300, 300 );
}

public static void main( String[] args ) {
    new DnDTemplate().setVisible( true );
}

class DndTransferHandler extends TransferHandler {

    private static final long serialVersionUID = 1L;

    @Override
    public boolean canImport( TransferHandler.TransferSupport info ) {
        // This gets called repeatedly while dragged file is over frame
        if ( !info.isDataFlavorSupported( DataFlavor.javaFileListFlavor ) ) {
            return false;
        }
        // Even though this method is called at the appropriate time, 
        // setting the cursor here is of no consequence
        info.getComponent().setCursor( dropCursor );

        return true;
    }

    @Override
    public boolean importData( TransferHandler.TransferSupport info ) {
        // this gets called when file is dropped
        if ( !info.isDrop() ) {
            return false;
        }

        Transferable transferable = info.getTransferable();
        String importFileName = null;
        try {
            List<File> fileList = (List<File>) transferable.getTransferData( DataFlavor.javaFileListFlavor );
            Iterator<File> iterator = fileList.iterator();
            while ( iterator.hasNext() ) {
                File f = iterator.next();
                importFileName = f.getAbsolutePath();
            }
            info.getComponent().setCursor( dropCursor );
            thePane.setCursor( dropCursor );

        } catch ( Exception e ) {
            return false;
        }

        System.out.println( "Importing " + importFileName );
        // Return the cursor back to the default
        thePane.setCursor( Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR ) );
        return true;
    }

}

}


6
不,这并没有回答问题。我看到过之前的内容并尝试使用setDropTarget。dragEnter方法会在适当的时间被调用,但光标仍然保持默认的拖放图标,不会更改为我指定的那个图标。 - agility
我尝试在dragOver中设置光标,但遇到了http://bugs.sun.com/view_bug.do?bug_id=4451328中提到的闪烁问题。也许这个问题并没有得到解决。 - tenorsax
1个回答

1

免责声明:这应该是一条评论而不是答案,但是它太长了无法适应评论。如果完全不正确,我将删除此答案

我没有测试过,但查看TransferHandler的API,我建议查看TransferHandler#getDragImage方法。

文档对于这个图像是否在从设置TransferHandler的组件启动拖动时使用,或者当从应用程序外部启动拖放并且光标经过设置TransferHandler的组件时也使用,有点不清楚。我找到了一个示例,似乎表明这在Java应用程序中肯定有效,但仍然不能确定来自外部应用程序的拖放。

错误编号 4816922 建议使用 TransferHandler#getVisualRepresentation,但不清楚该错误是否已被修复。


2
虽然我在问题中应该明确指定,但我正在寻找Java 6的解决方案。这仅在Java 7中实现。此外,在使用TransferHandler.setDragImage测试此解决方案时,调用似乎被忽略,并且拖动图标看起来与调用setDragImage时相同。 - agility

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接