2014-10-08 38 views
1

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

我tryed几个方面,如从这个适应: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(); 
} 

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

回答

1

如果通过Shape.subtract(...)创建Shape,则没有任何机制可以在事后更改其属性(用于更改用于创建它的形状的边界)。您必须从其父项中移除该形状,重新计算矩形和剪辑,重新计算形状,并将新形状重新添加到场景中。

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

我不确定你正在寻找什么功能,但是下面允许你通过点击和拖动它来拖动内部部分,并允许你通过点击和拖动外部来拖动整个窗口一部分。你应该足够了解你需要什么。我没有在你的例子中包含好的圆角,但你可以很容易地实现那些使用ArcTo路径元素。

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); 
    } 
} 
+0

不错的做法,非常感谢。我现在可以向前编码,但有两点:1.如何调整透明区域的大小2.我可以拖动透明区域的区域很难获得。我怎样才能让它变大? – 2014-10-08 13:39:56

+0

为了使内部区域可调整大小,为'innerRight'和'innerBottom'创建常规属性(不要将它们绑定到innerLeft和innerTop)。然后你可以独立操纵它们,从而改变尺寸。我不太清楚第二个问题,但在这个例子中,总面积只是由场景的大小('new Scene(root,800,600)')定义的。 – 2014-10-08 13:43:50

+0

对于第一个问题,我会尝试一下,第二个问题是,我将内部透明度更改为蓝色,以查看它是如何工作的。透明,很难拖动inne区域。 – 2014-10-08 13:48:37