【问题标题】:JavaFX how to center a Node to ImageView (with setPreserveRation == true)?JavaFX如何将节点居中到ImageView(使用setPreserveRation == true)?
【发布时间】:2018-12-03 01:54:25
【问题描述】:

我有一个resizableImageView,图像的某些部分应该是可点击的。 我的想法是创建一个GridPane,它将充当覆盖层并在其中放置几个​​透明按钮,这样当用户单击图像的某些部分时,他实际上会触发图像上的隐藏按钮:

<!-- parent that resizes from time to time -->
<StackPane>

    <StackPane>

        <!-- background image, preserves ration -->
        <ImageView/>

        <!-- overlay with transparent buttons -->
        <!-- should be positionion exactly the same as Image inside ImageView -->
        <GridPane>
            <!- buttons here, columns == rows -->
        </GridPane>

    </StackPane>

</StackPane>

代码如下所示:

    StackPane stackPane_wrapper = new StackPane();
    stackPane_wrapper.setAlignment(Pos.CENTER);

    //menu wheel
    WrappedImageView imageView_wheel = new WrappedImageView();
    imageView_wheel.setImage(new Image("images/menu-wheel.png"));
    imageView_wheel.setPreserveRatio(true);
    stackPane_wrapper.getChildren().add(imageView_wheel);

    GridPane gridPane_overlay = new GridPane();
    stackPane_wrapper.getChildren().add(gridPane_overlay);

    int size = 20;

    for (int i = 0; i < size; ++i)
    {
        ColumnConstraints columnConstraints = new ColumnConstraints();
        columnConstraints.setPercentWidth(100.0d / size);
        gridPane_overlay.getColumnConstraints().add(columnConstraints);

        RowConstraints rowConstraints = new RowConstraints();
        rowConstraints.setPercentHeight(100.0d / size);
        gridPane_overlay.getRowConstraints().add(rowConstraints);
    }

    Button button = new Button();
    button.setText("test");
    //... set style to make this button transparent
    gridPane_overlay.add(button, 3, 5, 2, 4);

我的问题是我无法将gridPane_overlay 放置在与ImageImageView 相同的位置。 Image inside imageView_wheel 不断调整大小和改变它的位置,这完全没问题,但我不知道如何将它的大小和位置分配给gridPane_overlay

我尝试将侦听器添加到各种 x/y 和宽度/高度属性,并且能够取得一些结果,但它停止工作,舞台变得最大化并继续设置完全无效的坐标。

更新:

似乎getParentInParent.getWidth()getParentInParent.getHeight()WrappedImageView 中返回了Image 的正确大小,现在我需要获取它的位置并将大小和位置都分配给网格。

更新 2:

基于cmets,我做了以下解决方案;

/**
 *
 * @param bounds bounds of image - result of {@link WrappedImageView#localToScene(Bounds)} from {@link WrappedImageView#getBoundsInLocal()}
 * @param x click X - {@link MouseEvent#getSceneX()} minus {@link Bounds#getMinX()}
 * @param y click Y - {@link MouseEvent#getSceneY()} minus {@link Bounds#getMinY()}
 * @return
 */
private int determineClick(Bounds bounds, double x, double y)
{
    double centerX = bounds.getWidth() / 2;
    double centerY = bounds.getHeight() / 2;

    double angle = Math.toDegrees(Math.atan2(x - centerX, y - centerY));

    Point2D center = new Point2D(centerX, centerY);
    Point2D click = new Point2D(x, y);
    double distance = center.distance(click);

    double diameter = centerX;
    boolean isInner = distance < diameter * 0.6;

    //-90 -> -135
    if (angle <= -90 && angle > -135)
    {
        if (isInner)
        {
            return 10;
        }

        return 0;
    }

    //-135 -> -180/180
    if (angle <= -135 && angle > -180)
    {
        if (isInner)
        {
            return 11;
        }

        return 1;
    }

    //-180/180 -> 135
    if (angle <= 180 && angle > 135)
    {
        if (isInner)
        {
            return 12;
        }

        return 2;
    }

    //135 -> 90
    if (angle <= 135 && angle > 90)
    {
        if (isInner)
        {
            return 13;
        }

        return 3;
    }

    //90 -> 45
    if (angle <= 90 && angle > 45)
    {
        if (isInner)
        {
            return 14;
        }

        return 4;
    }

    //45 -> -0/0
    if (angle <= 45 && angle > 0)
    {
        if (isInner)
        {
            return 15;
        }

        return 5;
    }

    //-0/0 -> -45
    if (angle <= 0 && angle > -45)
    {
        if (isInner)
        {
            return 16;
        }

        return 6;
    }

    //-45 -> -90
    if (angle <= -45 && angle > -90)
    {
        if (isInner)
        {
            return 17;
        }

        return 7;
    }

    throw new RuntimeException("Unable to determine point coordinates");
}

【问题讨论】:

  • 首先,您不希望GridPane 影响整个事物的实际大小,因此您不应该添加任何会这样做的文本。相反,GridPane 应该调整自己的大小以适应其父级可以给它的任何空间。其次,据我所知,所有透明节点都被排除在鼠标事件之外,因此使其完全透明可能行不通。
  • StackPane 处添加鼠标点击事件可能会更容易,并使用它来计算点击发生的位置,然后根据此执行您需要的任何操作。

标签: javafx layout imageview resize coordinates


【解决方案1】:

我也在想@Jai 在评论中提到的内容。您可以在 imageview 本身上包含一个鼠标单击事件,以确定在其边界的哪个点被单击。然后您可以确定点击位置的范围并执行您的逻辑。

类似...

imageView_wheel.setOnMouseClicked(e -> {
    Bounds bounds = imageView_wheel.localToScene(imageView_wheel.getBoundsInLocal());
    double x = e.getSceneX()-bounds.getMinX();
    double y = e.getSceneY()-bounds.getMinY();
    System.out.println("Clicked at :: "+x+","+y);
    // Now you know at what point in the image bounds is clicked, compute your logic as per your needs..
});

【讨论】:

    猜你喜欢
    • 2015-12-16
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多