实现JavaFX形状的拖放

时间:2013-11-18 11:32:51

标签: java animation drag-and-drop javafx-2 javafx

我是JavaFX动画的新手。我正在尝试将代码作为另一个大项目的试验; 基本上我想用鼠标拖动移动圆圈, 当圆圈在矩形上方时,突出显示矩形。 如果将圆圈拖放到矩形上,请将其颜色更改为圆形的颜色。

到目前为止,我已经设法用鼠标移动圆圈,但我不确定为什么矩形的OnDragEntered方法什么都不做。

这是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>

这是控制器:

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());
            }
        }
    }

这是正确的做法吗?或者我错误地混合了拖动和放大器放下动画? 对于那些想要使用它的人来说,它是实施色盲测试的开始。

1 个答案:

答案 0 :(得分:9)

我很久以前就发现了这个问题。但是没有时间在这里更新答案。虽然我必须说缺乏单一的回应令人惊讶。

moveCircle()方法中必须存在以下行:

    1. circle.setMouseTransparent(true);

确保圆形下的节点可以在拖动鼠标时检测拖动。

    2. event.consume();

确保消耗此事件,并且可以跟踪拖动检测事件。 highlightbox方法应包含:

event.acceptTransferModes(TransferMode.ANY);

我已经使用自定义事件处理程序完成了任务,而不是上面提到的那些因此我没有粘贴整个代码。