JavaFX之Drag And Drop拖放操作

时间:2021-02-24 16:59:59

大家好,新的JavaFX的教程又到来了。

  是不是很多程序都有拖动文件到程序里的功能?有没有感觉拖放操作很cool?我们的JavaFX当然也支持这样的操作。

  在JavaFX中,我们不仅可以从一个控件拖动内容到另外一个控件,还可以从系统拖动文件到JavaFX的控件,甚至还可以从一个JavaFX程序中拖动内容到另外一个JavaFX程序中。

  看起来不错吧?我们下面将会讲解在JavaFX中的拖放操作。


  首先,打个小广告。本人的个人博客地址: http://www.wjfxgame.com

  目前本人的JavaFX示例都可以在个人博客上面在线运行(除了部分)。虽然因为笔记本数据丢失,数量不多。不过本人也一直在编写中(由于在开发JavaFX游戏引擎,可能速度不会很快)。


  本篇教程的示例地址:  点击

  从Drag Me的标签拖动到 Drop On Me标签上。

  从本地,拖动一个图片 到 drag a image to this的标签下面,可以显示你拖动的图片。

  从本地,拖动一个文本文件 到 drag a txt to this的标签下面,可以显示你拖动的文本的内容(因为编码问题可能乱码,可以使用UTF-8等编码的文本)。


  截图:

  JavaFX之Drag And Drop拖放操作

  

  在JavaFX中关于拖放操作,可以设置这么几种事件监听器。

  setOnDragDetected(new EventHandler<MouseEvent>()); 

  当你从一个Node上进行拖动的时候,会检测到拖动操作,将会执行这个EventHandler。


  setOnDragEntered(new EventHandler<DragEvent>());

  当你拖动到目标控件的时候,会执行这个事件回调。


  setOnDragExited(new EventHandler<DragEvent>());

  当你拖动移出目标控件的时候,执行这个操作。


  setOnDragOver(new EventHandler<DragEvent>());

  当你拖动到目标上方的时候,会不停的执行。

 

  setOnDragDropped(new EventHandler<DragEvent>());

  当你拖动到目标并松开鼠标的时候,执行这个DragDropped事件。


  setOnDragDone(new EventHandler<DragEvent>());

  当你拖动并松手的时候,执行Drag完成操作。


  这里要注意的是,首先执行拖动,拖动到目标控件的时候,会首先执行DragEnter,这个只执行一遍。然后当你停留在目标控件上方的时候,会不停的指定DragOver操作。


  下面我们来看看示例中的代码:

  

[java]  view plain copy
  1. m_drag.setOnDragDetected(new EventHandler<MouseEvent>() {  
  2.   
  3.             @Override  
  4.             public void handle(MouseEvent event) {  
  5.                 Dragboard dragboard = m_drag.startDragAndDrop(TransferMode.ANY);  
  6.                 ClipboardContent content = new ClipboardContent();  
  7.                 content.putString(m_drag.getText());  
  8.                 dragboard.setContent(content);  
  9.             }  
  10.         });  
  11.   
  12.         m_drop.setOnDragEntered(new EventHandler<DragEvent>() {  
  13.   
  14.             @Override  
  15.             public void handle(DragEvent event) {  
  16.                 m_drop.setTextFill(Color.RED);  
  17.             }  
  18.         });  
  19.   
  20.         m_drop.setOnDragExited(new EventHandler<DragEvent>() {  
  21.   
  22.             @Override  
  23.             public void handle(DragEvent event) {  
  24.                 m_drop.setTextFill(Color.BLACK);  
  25.             }  
  26.         });  
  27.   
  28.         m_drop.setOnDragOver(new EventHandler<DragEvent>() {  
  29.   
  30.             @Override  
  31.             public void handle(DragEvent event) {  
  32.                 if (event.getGestureSource() != m_drop && event.getDragboard().hasString()) {  
  33.                     event.acceptTransferModes(TransferMode.COPY_OR_MOVE);  
  34.                 }  
  35.             }  
  36.         });  
  37.   
  38.         m_drop.setOnDragDropped(new EventHandler<DragEvent>() {  
  39.   
  40.             @Override  
  41.             public void handle(DragEvent event) {  
  42.                 Dragboard dragboard = event.getDragboard();  
  43.                 m_drop.setText(dragboard.getString());  
  44.             }  
  45.         });  
  46.   
  47.         m_drag.setOnDragDone(new EventHandler<DragEvent>() {  
  48.   
  49.             @Override  
  50.             public void handle(DragEvent event) {  
  51.                 m_drag.setText("");  
  52.             }  
  53.         });  

  其中m_drag是Drag Me标签Label。m_drop是Drop on Me标签Label。

  我们在检测到拖动m_drag标签的时候,使用了一个Dragboard,俗称"拖板"(...), 当然不能这样称呼,但是很明显,它就类似于ClipBoard剪切板。我们将拖动要传送的数据使用ClipboardContent设置到Dragboard上。

  

  其他的就是比较简单的,当拖动到m_drop上面的时候,改变m_drop的颜色。

  在DragOver的时候 通过event.acceptTransferModes(TransferMode.ANY);来设置接收数据的类型。

  在Drag松开的时候,通过获取Dragboard的数据,来设置到标签上。


  上面是JavaFX中 控件与控件之间拖动数据的示例。当然很多处理不得当,只是为了演示所有的拖动方法,所以才将每个事件都使用到。


  下面来看看拖动文件的:

  

[java]  view plain copy
  1. m_imageView.setOnDragOver(new EventHandler<DragEvent>() {  
  2.   
  3.             @Override  
  4.             public void handle(DragEvent event) {  
  5.                 if (event.getGestureSource() != m_imageView) {  
  6.                     event.acceptTransferModes(TransferMode.ANY);  
  7.                 }                 
  8.             }  
  9.         });  
  10.           
  11.         m_imageView.setOnDragDropped(new EventHandler<DragEvent>() {  
  12.   
  13.             @Override  
  14.             public void handle(DragEvent event) {  
  15.                 Dragboard dragboard = event.getDragboard();  
  16.                 List<File> files = dragboard.getFiles();  
  17.                 if(files.size() > 0){  
  18.                     try {  
  19.                         m_imageView.setImage(new Image(new FileInputStream(files.get(0))));  
  20.                     } catch (FileNotFoundException e) {  
  21.                         e.printStackTrace();  
  22.                     }  
  23.                 }  
  24.             }  
  25.         });  

  这里只有一个DragOver和DragDropped。

  松手之后,同样通过 Dragboard获取拖动的文件列表,我们这里将拖动到的第一个文件当作数据流创建图片并设置到imageView中。

  这里的操作比较简单,其实可以做更为复杂的判断。


  文本也是相同的:

 

[java]  view plain copy
  1. m_textArea.setOnDragOver(new EventHandler<DragEvent>() {  
  2.   
  3.     @Override  
  4.     public void handle(DragEvent event) {  
  5.         if (event.getGestureSource() != m_imageView) {  
  6.             event.acceptTransferModes(TransferMode.ANY);  
  7.         }                 
  8.     }  
  9. });  
  10.   
  11. m_textArea.setOnDragDropped(new EventHandler<DragEvent>() {  
  12.   
  13.     @Override  
  14.     public void handle(DragEvent event) {  
  15.         Dragboard dragboard = event.getDragboard();  
  16.         List<File> files = dragboard.getFiles();  
  17.         if(files.size() > 0){  
  18.             m_textArea.setText(FileTools.readFile(files.get(0)));  
  19.         }  
  20.     }  
  21. });  

  是不是很简单,当拖动操作在JavaFX程序中流行起来后,想一想我们可以从这个JavaFX程序拖动到另外一个JavaFX程序中,就会觉得很兴奋,或许会因此出现很多意想不到的应用(当然,前提是JavaFX能够被大家认可,广泛传播)。


   考虑到大家copy粘贴源代码修改看效果也不方便,以后本人的示例工程全部打包上传到CSDN下载栏目中,并且无需积分。

   本文章示例项目下载地址: http://download.csdn.net/detail/ml3947/5307918

   转载请注明出处: http://blog.csdn.net/ml3947

-----------------------------------------------------------------------------------------

   ...上传资源后,得了很久才显示出来。要是CSDN下载栏目效率太低,就传到其他地方去。