如图所示,这个例子是上一篇文章的例子修改而来的,实现了把右边列表的内容拖拽到左边的pane中去,结合上一篇列表的例子,本篇就讲解一下JavaFX中如何实现此类拖拽操作的功能。
首先用JavaFX Scene Builder创建一个fxml布局文件,分别添加一个Pane命名为“pane1”和一个ListView命名为“listView1”,并定义一个控制器类,来管理fxml里的控件,具体的方法之前的文章介绍过,不再阐述。
为了实现图中的功能需要三个操作:
点击右边列表中的某一项,按住鼠标开始拖拽。
按住鼠标,移动到目标Pane上,鼠标指针变成添加的标识。
在目标Pane上松开鼠标,把指定内容设置到Pane上完成操作。
对应的,这里需要实现三个拖拽事件监听器,分别是DragStartHandle、DragMoveHandler、DragOverHandler。
DragStartHandle
即处理拖拽起始的行为,代码如下:
public class DragStartHandle implements EventHandler<MouseEvent> { private Node source;
private String str;
public DragStartHandle(Node source, String str) { this.source = source; this.str = str; }
public void handle(MouseEvent event) { Dragboard db = source.startDragAndDrop(TransferMode.COPY); ClipboardContent content = new ClipboardContent(); content.putString(str); db.setContent(content); event.consume(); } } |
handle事件中,实现了将当前选中列表项的数据放到剪切板里。这个监听器是设置给列表项的,用以处理点击拖拽列表项的事件,ListCell中的代码如下:
public class CustomListCell extends ListCell<String> { private JavaFxTestMain controller;
public CustomListCell(JavaFxTestMain controller) { this.controller = controller; }
@Override public void updateItem(final String item, boolean empty) { super.updateItem(item, empty); if (item != null) { HBox hbox = new HBox(10); hbox.setAlignment(Pos.CENTER); Label label = new Label(item); Button button = new Button("删除" + item); button.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent event) { controller.deleteListItem(item); } }); hbox.setOnDragDetected(new DragStartHandle(hbox, item)); hbox.getChildren().addAll(label, button); setGraphic(hbox); } } } |
红色区域的代码即是给指定控件(Node)添加拖拽起始的监听器。
DragMoveHandler
处理拖拽移动中的事件:
public class DragMoveHandler implements EventHandler<DragEvent> { public void handle(DragEvent event) { Dragboard db = event.getDragboard(); if (db.hasString()) { event.acceptTransferModes(TransferMode.COPY); }
event.consume(); } } |
DragOverHandler
处理拖拽结束事件:
public class DragOverHandler implements EventHandler<DragEvent> {
private JavaFxTestMain contrller;
public DragOverHandler(JavaFxTestMain contrller) { this.contrller = contrller; }
public void handle(DragEvent event) { Dragboard db = event.getDragboard(); boolean success = false; if (db.hasString()) { contrller.addTextToPane(event.getX(), event.getY(), db.getString()); success = true; } event.setDropCompleted(success); event.consume(); } } |
这里我们要将刚才DragStartHandler添加到剪切板的内容取出,并添加到pane指定位置上去。在控制类里实现了一个addTextToPane方法,用以添加指定Text到panel的指定位置:
public void addTextToPane(double x, double y, String str) { Text text = new Text(x, y, str); pane1.getChildren().add(text); } |
DragMoveHandler和DragOverHanlder事件是需要panel监听的,最后给panel设置这两个监听器即可:
pane1.setOnDragOver(new DragMoveHandler()); pane1.setOnDragDropped(new DragOverHandler(this)); |
源码下载:
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。