将外部文件拖动到 Swing 应用程序时设置自定义光标
我有一个 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;
}
}
}
I have a swing application into which I would like to import an external file by dragging the external file from windows explorer onto the application. I have this basic functionality working. However, I would like to change the default drag/drop cursor icon into an application appropriate cursor. I have not been able to change the cursor visible to the user while the mouse key is pressed and is held over the application. I have seen examples of this working if the drag and drop operation is within the same swing application. I have attempted to accomplish this using a DragGestureListener and DragSource to no avail. It seems that those methods are not called unless the drag source is within swing. Is it possible to change the drag cursor when dragging an external file into a swing application?
Please see this simplified example:
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;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
免责声明:这应该是一条评论,而不是一个答案,但它太长了,不适合评论。如果它完全不正确,我将删除这个答案
我没有对此进行测试,而是查看
TransferHandler
我建议看一下TransferHandler#getDragImage
方法。文档有点不清楚当从设置了 TransferHandler 的组件发起拖动时是否使用此图像,或者当从应用程序和光标外部发起拖动时也使用该图像来自为其设置了 TransferHandler 的组件。我找到了一个例子 这似乎表明这在 Java 应用程序中确实有效,但对于来自外部应用程序的拖放仍然没有定论
Bug ID 4816922 建议使用
TransferHandler#getVisualRepresentation
但尚不清楚该错误是否已修复。Disclaimer: this should have been a comment and not an answer, but it is just too long to fit in the comments. I will delete this answer if it is completely incorrect
I did not test this but looking at the API of
TransferHandler
I would suggest to take a look at theTransferHandler#getDragImage
method.The documentation is a bit unclear on whether this image is used when the drag is initiated from the component for which the
TransferHandler
is set, or also used when a drag is initiated from outside of the application and the cursor comes over the component for which theTransferHandler
is set. I found an example which seems to suggest this certainly works in Java application, but still inconclusive about drag-and-drop coming from an external applicationBug ID 4816922 suggests to use the
TransferHandler#getVisualRepresentation
but it is unclear whether the bug is already fixed.