Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement drag-and-drop like in Scene Builder

I'm building an application in JavaFx 2.2 which consist in a splitpane with a panel of component on the left side and a working sheet on the right side. Basically what i would like to do is a simple wysiwyg editor where you drag component from the left to the right, then arrange them on the right side.

I've spent the last couple of days trying to implement the same drag-and-drop feature that has SceneBuilder, without luck..

Following the sample at http://docs.oracle.com/javafx/2/drag_drop/HelloDragAndDrop.java.html i've managed to get a drag-and-drop working but i can't find any way to change the default file icon appearing when you are dragging (and replace it with a snapshot of the component i'm dragging) and how to show the forbidden icon when you are over something you can't dropped on.

Any help (could be advice, code snippet, sample or else) would be greatly appreciated :)

Thanks !

like image 827
Badisi Avatar asked Nov 29 '12 11:11

Badisi


People also ask

How do I drag and drop in JavaFX?

Moreover, drag-and-drop can be implemented between a JavaFX application and a third-party (native) application such as Windows Explorer or a desktop. A drag-and-drop gesture happens as follows: The user click a mouse button on a gesture source, drags the mouse, and releases the mouse button on a gesture target.

How do I drag a shape in JavaFX?

Dragging shapes can be accomplished by attaching Listeners to a target node's MouseEvents. These intercept JavaFX's click-drag-release cycle to store the initial position of the node, and the total mouse movement. This allows the real-time position of the node to be calculated as it is dragged.

What is gluon Scene Builder?

Gluon Scene Builder is a drag and drop UI designer tool allowing rapid desktop and mobile app development. Scene Builder separates design from logic, allowing team members to quickly and easily focus on their specific aspect of application development.


2 Answers

[UPDATE]

Finally managed it myself:

/* The 'sceneRoot' object is the root Node of the scene graph
 *    stage.setScene(new Scene(sceneRoot, 1280, 1024));
 */

private ImageView dragImageView = new ImageView();
private Node dragItem;

_

rightPane.setOnMouseDragEntered(new EventHandler<MouseDragEvent>() {
    public void handle(MouseDragEvent e) {
        rightPane.setStyle("-fx-border-color:red;-fx-border-width:2;-fx-border-style:solid;");
        e.consume();
    }
});
rightPane.setOnMouseDragExited(new EventHandler<MouseDragEvent>() {
    public void handle(MouseDragEvent e) {
        rightPane.setStyle("-fx-border-style:none;");
        e.consume();
    }
});
rightPane.setOnMouseDragReleased(new EventHandler<MouseDragEvent>() {
    public void handle(MouseDragEvent e) {
        //TODO: add new instance of dragItem to rightPane
        e.consume();
    }
});

_

private void addGesture(final Node node) {
    node.setOnDragDetected(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent e) {

            SnapshotParameters snapParams = new SnapshotParameters();
            snapParams.setFill(Color.TRANSPARENT);
            dragImageView.setImage(node.snapshot(snapParams, null));

            sceneRoot.getChildren().add(dragImageView);

            dragImageView.startFullDrag();
            e.consume();
        }
    });
    node.setOnMouseDragged(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent e) {
            Point2D localPoint = sceneRoot.sceneToLocal(new Point2D(e.getSceneX(), e.getSceneY()));
            dragImageView.relocate(
                    (int)(localPoint.getX() - dragImageView.getBoundsInLocal().getWidth() / 2),
                    (int)(localPoint.getY() - dragImageView.getBoundsInLocal().getHeight() / 2)
            );
            e.consume();
        }
    });
    node.setOnMouseEntered(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent e) {
            node.setCursor(Cursor.HAND);
        }
    });
    node.setOnMousePressed(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent e) {
            dragItem = node;
            dragImageView.setMouseTransparent(true);
            node.setMouseTransparent(true);
            node.setCursor(Cursor.CLOSED_HAND);
        }
    });
    node.setOnMouseReleased(new EventHandler<MouseEvent>() {
        public void handle(MouseEvent e) {
            dragItem = null;
            dragImageView.setMouseTransparent(false);
            node.setMouseTransparent(false);
            node.setCursor(Cursor.DEFAULT);
            sceneRoot.getChildren().remove(dragImageView);
        }
    });

}
like image 50
Badisi Avatar answered Sep 25 '22 09:09

Badisi


Maybe late, but with the setDragView option, is more simpple by now :)

// Cursor Display for Drag&Drop
source.setOnMouseEntered(e -> source.setCursor(Cursor.OPEN_HAND));
source.setOnMousePressed(e -> source.setCursor(Cursor.CLOSED_HAND));
source.setOnMouseReleased(e -> source.setCursor(Cursor.DEFAULT));

// Manage drag
source.setOnDragDetected(event -> {
    /* drag was detected, start a drag-and-drop gesture*/
    Dragboard db = source.startDragAndDrop(TransferMode.MOVE);

    // Visual during drag
    SnapshotParameters snapshotParameters = new SnapshotParameters();
    snapshotParameters.setFill(Color.TRANSPARENT);
    db.setDragView(source.snapshot(snapshotParameters, null));

    /* Put a string on a dragboard */
    ClipboardContent content = new ClipboardContent();
    content.putString(source.getText());
    db.setContent(content);

    event.consume();
});
like image 21
LE GALL Benoît Avatar answered Sep 24 '22 09:09

LE GALL Benoît