超过一半重叠时突出显示矩形

时间:2017-07-31 12:52:26

标签: javafx drag

我有一个JavaFX应用程序,其窗格包含矩形。可以通过拖动鼠标来移动这些矩形。

当我将一个矩形拖到另一个矩形上时,我想要突出显示第二个(背景)矩形。这有效,见下面的代码

private boolean moveInProgress;
private Point2D prevPos;

public void onMousePressed(MouseEvent event) {
    setMouseTransparent(true);
    Point2D point = new Point2D(event.getSceneX(), event.getSceneY());

    if (!moveInProgress) {
        moveInProgress = true;

        prevPos = point;
        LOG.debug("Mouse move started on location " + prevPos);
    }

    event.consume();
}

public void onMouseDragged(MouseEvent event) {
    if (moveInProgress) {
        Point2D point = new Point2D(event.getSceneX(), event.getSceneY());
        this.toFront();

        double[] translationVector = new double[2];
        translationVector[0] = point.getX() - prevPos.getX();
        translationVector[1] = point.getY() - prevPos.getY();

        setTranslateX(getTranslateX() + translationVector[0]);
        setTranslateY(getTranslateY() + translationVector[1]);

        prevPos = point;
    }

    event.consume();
}

public void onMouseReleased(MouseEvent event) {
    setMouseTransparent(false);

    if (moveInProgress) {
        moveInProgress = false;
    }
    event.consume();
}

public void onDragDetected(MouseEvent event) {
    startFullDrag();
    event.consume();
}

public void onMouseDragEntered(MouseDragEvent event) {
    getStyleClass().add("drag-target");
    event.consume();
}

public void onMouseDragExited(MouseDragEvent event) {
    if (getStyleClass().contains("drag-target")) {
        getStyleClass().remove("drag-target");
    }
    event.consume();
}

当拖动矩形的一半以上重叠时,我想突出显示底层矩形。在这张图片中,我想突出显示红色矩形,因为灰色矩形重叠了一半以上。

问题是MouseDragEntered和MouseDragExited事件是根据我的鼠标位置触发的。当我的鼠标位置是例如图片中的黑点时,我的鼠标事件将仅在我的鼠标进入红色矩形时触发。

在灰色矩形的拖动动作中,有没有人能给我一些指示如何突出红色矩形,超过一半重叠?

Rectangles

1 个答案:

答案 0 :(得分:0)

一种方法是让每个矩形观察被拖动的矩形的边界。然后使用Shape.intersect(或通过其他方法)进行计算是相当容易的,以查看矩形是否被拖动的矩形覆盖了50%。这里棘手的部分是将侦听器添加到被拖动的矩形中,并在矩形停止拖动时再次移除它们。

这是一个简单的例子。我认为我的设置与你设置的方式略有不同,但你应该能够很容易地将它调整到你的用例。

import java.util.Random;

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.css.PseudoClass;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;

public class DraggingHighlightRectangles extends Application {

    private final Random rng = new Random();
    private final ObjectProperty<Rectangle> draggingRectangle = new SimpleObjectProperty<>();

    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        pane.setMinSize(600, 600);

        Button newRectButton = new Button("New Rectangle");
        newRectButton.setOnAction(e -> pane.getChildren().add(createRectangle()));

        BorderPane.setAlignment(newRectButton, Pos.CENTER);
        BorderPane.setMargin(newRectButton, new Insets(5));

        BorderPane root = new BorderPane(pane);
        root.setBottom(newRectButton);

        Scene scene = new Scene(root);
        scene.getStylesheets().add("style.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Rectangle createRectangle() {
        Rectangle rect = new Rectangle(rng.nextInt(400)+100, rng.nextInt(500)+50, 100, 50);
        rect.setFill(randomColor());
        rect.getStyleClass().add("rect");

        ChangeListener<Bounds> boundsListener = (obs, oldBounds, newBounds) -> {
            double myArea = rect.getWidth() * rect.getHeight() ;
            Shape intersection = Shape.intersect(draggingRectangle.get(), rect);
            Bounds intersectionBounds = intersection.getBoundsInLocal();
            double intersectionArea = intersectionBounds.getWidth() * intersectionBounds.getHeight() ;
            rect.pseudoClassStateChanged(PseudoClass.getPseudoClass("highlight"), intersectionArea >= 0.5 * myArea);
        };

        draggingRectangle.addListener((obs, oldRect, newRect) -> {
            if (oldRect != null) {
                oldRect.boundsInLocalProperty().removeListener(boundsListener);
            }
            if (newRect != null && newRect != rect) {
                newRect.boundsInLocalProperty().addListener(boundsListener);
            }
            rect.pseudoClassStateChanged(PseudoClass.getPseudoClass("highlight"), false);
        });

        class MouseLocation { double x, y ; }
        MouseLocation mouseLocation = new MouseLocation();

        rect.setOnMousePressed(e -> {
            draggingRectangle.set(rect);
            rect.toFront();
            mouseLocation.x = e.getX() ;
            mouseLocation.y = e.getY() ;
        });

        rect.setOnMouseDragged(e -> {
            rect.setX(rect.getX() + e.getX() - mouseLocation.x);
            rect.setY(rect.getY() + e.getY() - mouseLocation.y);
            mouseLocation.x = e.getX() ;
            mouseLocation.y = e.getY() ;
        });

        rect.setOnMouseReleased(e -> draggingRectangle.set(null));

        return rect ;
    }

    private Color randomColor() {
        return Color.rgb(rng.nextInt(256), rng.nextInt(256), rng.nextInt(256));
    }

    public static void main(String[] args) {
        launch(args);
    }
}

我的样式表style.css只包含

.rect:highlight {
    -fx-fill: yellow ;
}