2014-10-08 62 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