Ruturaj Patil
Ruturaj Patil

Reputation: 608

implementing drag and drop for shapes JavaFX

I'm new to JavaFX animation. I'm trying following code as a trial for another big project; Basically I want to move circles with mouse drag, when circle is over rectangle, highlight rectangle. If circle is dropped onto rectangle, change its color to that of circle's.

So far I've managed to move circle with mouse but I'm not sure why rectangle's OnDragEntered method does nothing.

Here's the FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.text.*?>

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sc.colordx.controller.D15Controller">
  <children>
<Rectangle fx:id="r1" arcHeight="5.0" arcWidth="5.0" fill="WHITE" height="152.0" layoutX="33.0" layoutY="14.0" onDragDropped="#fillBox" onDragEntered="#highlightBox" pickOnBounds="true" stroke="BLACK" strokeType="INSIDE" width="52.5" />
<Rectangle fx:id="r2" arcHeight="5.0" arcWidth="5.0" fill="WHITE" height="152.0" layoutX="91.0" layoutY="14.0" onDragDropped="#fillBox" onDragEntered="#highlightBox" stroke="BLACK" strokeType="INSIDE" width="52.5" />
<Circle fx:id="c1" fill="DODGERBLUE" layoutX="348.0" layoutY="262.0" onDragDetected="#startDrag" onMouseDragged="#moveCircle" onMouseReleased="#removeBind" radius="54.5" stroke="BLACK" strokeType="INSIDE" />
<Circle id="c1" fx:id="c2" fill="#ff3d00" layoutX="217.0" layoutY="262.0" onDragDetected="#startDrag" onMouseDragged="#moveCircle" onMouseReleased="#removeBind" radius="54.5" stroke="BLACK" strokeType="INSIDE" />
  </children>
</AnchorPane>

And here's the controller:

package com.sc.colordx.controller;

    import java.awt.Point;
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.animation.TranslateTransition;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.input.DragEvent;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.shape.Circle;
    import javafx.scene.shape.Rectangle;
    import javafx.util.Duration;


        public class D15Controller implements Initializable {
        @FXML
        private Circle c1;
        @FXML
        private Rectangle r1;

        // Animation Data
        private static final Duration TRANSLATE_DURATION      = Duration.seconds(0.25);
        private TranslateTransition transition;
        @FXML
        private Circle c2;
        @FXML
        private Rectangle r2;
        /**
         * Initializes the controller class.
         */
        @Override
        public void initialize(URL url, ResourceBundle rb) 
        {
            // TODO
            transition = createTranslateTransition(c1);


        }    
        private TranslateTransition createTranslateTransition(final Circle circle) {
        final TranslateTransition transition = new TranslateTransition(TRANSLATE_DURATION, circle);

        return transition;
        }

        @FXML
        private void removeBind(MouseEvent event) 
        {
            if(event.getSource() instanceof Circle)
            {
                Circle circle = (Circle)event.getSource();
                circle.setOpacity(1);
            }
        }

            private void fillBox(DragEvent event) 
        {
            System.out.println("Drag detected");
            if(event.getGestureTarget() instanceof Rectangle)
            {
                Rectangle target=(Rectangle)event.getGestureTarget();
                Circle source=(Circle)event.getGestureSource();
                target.setFill(source.getFill());
            }
        }
            @FXML
        private void moveCircle(MouseEvent event) 
        {
             Circle circle=null;
            event.setDragDetect(true);

            if(event.getSource() instanceof Circle)
            {

                circle=(Circle)event.getSource();

                circle.setOpacity(0.25);
                if (!event.isControlDown()) 
                {
                    circle.setCenterX(event.getX());
                    circle.setCenterY(event.getY());
                }   
                else 
                {
                    transition.setToX(circle.getCenterX());
                    transition.setToY(circle.getCenterY());
                    transition.playFromStart();
                }
            }


        }

       @FXML
        private void startDrag(MouseEvent event)
        {
            if(event.getSource() instanceof  Circle)
            {
                Circle source=(Circle)event.getSource();
                source.startFullDrag();
            }
        }
        @FXML
            private void highlightBox(DragEvent event) 
        {
            System.out.println("Highlight box");
            if(event.getGestureSource() instanceof Circle)
            {
                Circle source=(Circle)event.getGestureSource();
                Rectangle target=(Rectangle)event.getGestureTarget();
                target.setFill(source.getFill());
            }
        }
    }

Is this the right approach? Or am I incorrectly mixing drag & drop with animation ? For those wondering about use of this, its a start for implementing color blindness test.

Upvotes: 0

Views: 6483

Answers (1)

Ruturaj Patil
Ruturaj Patil

Reputation: 608

Well I figured out the problem long time ago. But didnt have time to update the answer here. Although I must say the lack of a single response is surprising.

Following lines must be present in the moveCircle() method:

    1. circle.setMouseTransparent(true);

ensures that nodes under circle can detect drag when mouse is dragged.

    2. event.consume();

ensures this event is consumed and drag detect event can follow up. The highlightbox method should contain:

event.acceptTransferModes(TransferMode.ANY);

I've completed the task with custom event handlers instead of the ones mentioned above hence I'm not pasting the entire code.

Upvotes: 9

Related Questions