23
2013
08

JavaFX实现拖拽

2013-08-23_110019.png

如图所示,这个例子是上一篇文章的例子修改而来的,实现了把右边列表的内容拖拽到左边的pane中去,结合上一篇列表的例子,本篇就讲解一下JavaFX中如何实现此类拖拽操作的功能。


首先用JavaFX Scene Builder创建一个fxml布局文件,分别添加一个Pane命名为“pane1”和一个ListView命名为“listView1”,并定义一个控制器类,来管理fxml里的控件,具体的方法之前的文章介绍过,不再阐述。

为了实现图中的功能需要三个操作:

  1. 点击右边列表中的某一项,按住鼠标开始拖拽。

  2. 按住鼠标,移动到目标Pane上,鼠标指针变成添加的标识。

  3. 在目标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));


源码下载:

DragTest.zip

« 上一篇下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。