JavaFX之组件拖放操作

示例内容:

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

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

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

截图如下:

在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操作。

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

m_drag.setOnDragDetected(new EventHandler() {

			@Override
			public void handle(MouseEvent event) {
				Dragboard dragboard = m_drag.startDragAndDrop(TransferMode.ANY);
				ClipboardContent content = new ClipboardContent();
				content.putString(m_drag.getText());
				dragboard.setContent(content);
			}
		});

		m_drop.setOnDragEntered(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				m_drop.setTextFill(Color.RED);
			}
		});

		m_drop.setOnDragExited(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				m_drop.setTextFill(Color.BLACK);
			}
		});

		m_drop.setOnDragOver(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				if (event.getGestureSource() != m_drop && event.getDragboard().hasString()) {
					event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
				}
			}
		});

		m_drop.setOnDragDropped(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				Dragboard dragboard = event.getDragboard();
				m_drop.setText(dragboard.getString());
			}
		});

		m_drag.setOnDragDone(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				m_drag.setText("");
			}
		});

其中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中 控件与控件之间拖动数据的示例。当然很多处理不得当,只是为了演示所有的拖动方法,所以才将每个事件都使用到。

下面来看看拖动文件的:

m_imageView.setOnDragOver(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				if (event.getGestureSource() != m_imageView) {
					event.acceptTransferModes(TransferMode.ANY);
				}				
			}
		});
		
		m_imageView.setOnDragDropped(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				Dragboard dragboard = event.getDragboard();
				List files = dragboard.getFiles();
				if(files.size() > 0){
					try {
						m_imageView.setImage(new Image(new FileInputStream(files.get(0))));
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					}
				}
			}
		});

这里只有一个DragOverDragDropped

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

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

文本也是相同的:

m_textArea.setOnDragOver(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				if (event.getGestureSource() != m_imageView) {
					event.acceptTransferModes(TransferMode.ANY);
				}				
			}
		});
		
		m_textArea.setOnDragDropped(new EventHandler() {

			@Override
			public void handle(DragEvent event) {
				Dragboard dragboard = event.getDragboard();
				List files = dragboard.getFiles();
				if(files.size() > 0){
					m_textArea.setText(FileTools.readFile(files.get(0)));
				}
			}
		});

发表评论

电子邮件地址不会被公开。