调整减法形状的大小 [英] resizing a substraction shape

查看:141
本文介绍了调整减法形状的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想调整下面创建的形状的大小。但无法得到它。
该项目是创建一个透明矩形,仅显示桌面的一部分,并隐藏其余部分。透明区域是减法的结果,我需要让用户调整大小。

I would like to resize the below created shape. but cannot get it. The project is to create a transparent rectangle to show only a part of the desktop, and hide the rest. The transparent zone is the result of a substraction, and I need to make it resizable by the user.

我尝试了几种方法,例如适应: https://gist.github.com/jewelsea/1441960

I tryed several ways, such as adapting from this : https://gist.github.com/jewelsea/1441960

但无法得到它。

这是我的代码:

@Override
public void start(Stage stage) {
    Group group = new Group();
    Rectangle rect = new Rectangle(0, 0, 350, 300);
    Rectangle clip = new Rectangle(20, 20, 200, 200);
    clip.setArcHeight(15);
    clip.setArcWidth(15);

    Shape shape = Shape.subtract(rect, clip);

    shape.setFill(Color.GRAY);
    group.getChildren().add(shape);
    Scene scene = new Scene(group);
    scene.setFill(Color.TRANSPARENT);
    stage.initStyle(StageStyle.TRANSPARENT);
    stage.setScene(scene);
    stage.show();
}

任何链接或帮助都将不胜感激。

Any link or help would be appreciated.

推荐答案

如果您通过 Shape.subtract(...)创建 Shape ,之后你没有任何机制来改变它的属性(从改变用于创建它的形状边界的意义上来说)。您必须从其父项中删除形状,重新计算矩形和剪辑,重新计算形状,然后将新形状添加回场景。

If you create a Shape by Shape.subtract(...), you don't have any mechanism to change the properties of it afterwards (in the sense of changing the bounds of the shapes that were used to create it). You would have to remove the shape from its parent, recompute the rect and clip, recompute the shape, and add the new shape back into the scene.

可能更好在这里使用路径,这样您就可以在不创建新形状的情况下操纵坐标。围绕外部(填充部分)以一种方式(例如顺时针方向)移动,然后在内部(透明部分)周围以另一种方式(逆时针方向)移动。得到的形状与内部从外部减去的形状相同。初始设置可能需要更多代码,但您可以根据需要操作坐标。

It might be better to use a Path here so that you can manipulate the coordinates without creating a new shape every time. Traverse one way (say clockwise) around the outside (filled portion), and then the other way (anti-clockwise) around the inner (transparent portion). The resulting shape will be the same as a subtraction of the inner portion from the outer portion. The initial setup will potentially require considerably more code, but you can then manipulate the coordinates as you need to.

我不确定您正在寻找什么功能,但是以下内容允许您通过单击并拖动它来拖动内部部分,并允许您通过单击并拖动外部部分来移动整个窗口。它应该足以让你弄清楚你需要什么。我没有在你的示例中包含漂亮的圆角,但你可以使用 ArcTo 路径元素轻松实现它们。

I'm not sure exactly what functionality you were looking for, but the following allows you to drag the inner portion around by clicking and dragging on it, and allows you to move the whole window by clicking and dragging on the outer portion. It should be enough for you to figure out what you need. I didn't include the nice rounded corners you had in your example, but you can fairly easily implement those using ArcTo path elements.

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ObservableDoubleValue;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.ClosePath;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.PathElement;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class TransparentRectangle extends Application {


    @Override
    public void start(Stage stage) {

        Pane root = new Pane();

        PathElement start = new MoveTo(0, 0);
        PathElement outerTopRight = createBoundLineTo(root.widthProperty(), 0);
        PathElement outerBottomRight = createBoundLineTo(root.widthProperty(), root.heightProperty());
        PathElement outerBottomLeft = createBoundLineTo(0, root.heightProperty());
        PathElement outerTopLeft = new LineTo(0, 0);

        DoubleProperty innerLeft = new SimpleDoubleProperty(20);
        DoubleProperty innerTop = new SimpleDoubleProperty(20);
        DoubleBinding innerRight = innerLeft.add(180);
        DoubleBinding innerBottom = innerTop.add(180);

        PathElement innerTopLeft = createBoundLineTo(innerLeft, innerTop);
        PathElement innerTopRight = createBoundLineTo(innerRight, innerTop);
        PathElement innerBottomRight = createBoundLineTo(innerRight, innerBottom);
        PathElement innerBottomLeft = createBoundLineTo(innerLeft, innerBottom);

        Path path = new Path(
                start, outerTopRight,
                outerBottomRight, outerBottomLeft,
                outerTopLeft, 
                innerTopLeft, innerBottomLeft, 
                innerBottomRight, innerTopRight,
                innerTopLeft, new ClosePath()
        );


        path.setFill(Color.GRAY);
        path.setStroke(Color.TRANSPARENT);
        root.getChildren().add(path);

        class Wrapper<T> { T value ; }
        Wrapper<Point2D> mouseLocation = new Wrapper<>();

        // Drag on gray portion of path - move entire window:
        path.setOnDragDetected(event -> {
            mouseLocation.value = new Point2D(event.getScreenX(), event.getScreenY());
        });
        path.setOnMouseDragged(event -> {
            if (mouseLocation.value != null) {
                stage.setX(stage.getX() + event.getScreenX() - mouseLocation.value.getX());
                stage.setY(stage.getY() + event.getScreenY() - mouseLocation.value.getY());
                mouseLocation.value = new Point2D(event.getScreenX(), event.getScreenY());
            }
        });
        path.setOnMouseReleased(event -> mouseLocation.value = null);


        // Drag on scene (i.e not on path, i.e. on transparent part) - move transparent part
        root.setOnDragDetected(event -> {
            mouseLocation.value = new Point2D(event.getScreenX(), event.getScreenY());
        });
        root.setOnMouseDragged(event -> {
            if (mouseLocation.value != null) {
                innerLeft.set(innerLeft.get() + event.getScreenX() - mouseLocation.value.getX());
                innerTop.set(innerTop.get() + event.getScreenY() - mouseLocation.value.getY());
                mouseLocation.value = new Point2D(event.getScreenX(), event.getScreenY());
            }
        });
        root.setOnMouseReleased(event -> mouseLocation.value = null);

        // No close button on a transparent window, so exit on double click:
        root.setOnMouseClicked(event -> {
            if (event.getClickCount() == 2) Platform.exit();
            event.consume();
        });

        Scene scene = new Scene(root, 800, 600);

        scene.setFill(Color.TRANSPARENT);
        stage.initStyle(StageStyle.TRANSPARENT);
        stage.setScene(scene);
        stage.show();
    }

    private PathElement createBoundLineTo(ObservableDoubleValue x, ObservableDoubleValue y) {
        LineTo lineTo = new LineTo();
        lineTo.xProperty().bind(x);
        lineTo.yProperty().bind(y);
        return lineTo ;
    }

    private PathElement createBoundLineTo(double fixedX, ObservableDoubleValue y) {
        LineTo lineTo = new LineTo();
        lineTo.setX(fixedX);
        lineTo.yProperty().bind(y);
        return lineTo ;
    }

    private PathElement createBoundLineTo(ObservableDoubleValue x, double fixedY) {
        LineTo lineTo = new LineTo();
        lineTo.setY(fixedY);
        lineTo.xProperty().bind(x);
        return lineTo ;
    }

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

这篇关于调整减法形状的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆