【问题标题】:Set custom cursor when dragging external file into Swing app将外部文件拖入 Swing 应用程序时设置自定义光标
【发布时间】:2012-01-17 17:16:15
【问题描述】:

我有一个 Swing 应用程序,我想通过将外部文件从 Windows 资源管理器拖到应用程序上来导入外部文件。我有这个基本功能工作。但是,我想将默认的拖放光标图标更改为应用程序适当的光标。当鼠标键被按下并保持在应用程序上时,我无法更改用户可见的光标。如果拖放操作在同一个 Swing 应用程序中,我已经看到了这种工作的示例。我试图使用 DragGestureListener 和 DragSource 来完成此操作,但无济于事。除非拖动源在摆动范围内,否则似乎不会调用这些方法。将外部文件拖入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;
    }

}

}

【问题讨论】:

  • 不,这没有回答问题。我确实看到了以前并尝试使用 setDropTarget。 dragEnter 方法确实在适当的时候被调用,但是光标保持默认的拖放图标,不会更改为我指定的那个。
  • 我尝试在dragOver设置光标,遇到bugs.sun.com/view_bug.do?bug_id=4451328中提到的闪烁。可能它毕竟不是固定的。

标签: swing java-6


【解决方案1】:

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

我没有对此进行测试,但查看TransferHandler 的API,我建议查看TransferHandler#getDragImage 方法。

文档有点不清楚是从设置了TransferHandler的组件启动拖动时使用此图像,还是从应用程序外部启动拖动并且光标过来时使用此图像设置了TransferHandler 的组件。我发现 an example 这似乎表明这在 Java 应用程序中确实有效,但对于来自外部应用程序的拖放仍然没有定论

Bug ID 4816922 建议使用TransferHandler#getVisualRepresentation,但不清楚该错误是否已经修复。

【讨论】:

  • 虽然我应该在我的问题中指定,但我正在寻找 Java 6 中的解决方案。这仅在 Java 7 中实现。此外,在使用 TransferHandler.setDragImage 测试此解决方案时,调用似乎被忽略,拖动图标在调用和不调用 setDragImage 时显示相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-30
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 2011-10-08
相关资源
最近更新 更多