我如何隐藏场景之外的元素部分? JavaFX的

时间:2015-01-28 14:55:30

标签: javafx scene

这是一个很难解释的情况,我会尽力而为。

我需要做一个圆形窗格或一个隐藏圆圈区域之外的元素(节点)部分的场景。我的意思是,我不想只隐藏外面的区域。就像一个“.setClip”。我无法使用最后一种方法,因为项目是动画,当我移动节点时,剪辑也会移动。

当文本出现时,这就是我想要做的。

Example

这是我项目中的图片。红色标记显示问题。

enter image description here

谢谢!

PD:这是DocumentController Link

1 个答案:

答案 0 :(得分:3)

setClip()有什么问题?如果以下内容未能为您提供所需答案,请提供完整的代码示例,说明问题所在。

剪辑图像(即没有文字)

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class ClipImage extends Application {

    @Override
    public void start(Stage primaryStage) {

        Group root = new Group();

        // background image
        ImageView imageView = new ImageView( "http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg");

        // some text
        Label label = new Label( "This is a Tiger. Tigers are awesome!");
        label.relocate(20, 400);
        label.setTextFill(Color.RED);
        label.setFont(new Font("Tahoma", 48));

        root.getChildren().addAll( imageView, label);

        Scene scene = new Scene( root, 1024, 768);

        primaryStage.setScene( scene);
        primaryStage.show();

        // pane with clipped area
        CirclePane circlePane = new CirclePane();
        makeDraggable( circlePane);

        root.getChildren().addAll( circlePane);

    }

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


    private class CirclePane extends Pane {

        public CirclePane() {

            // load image
//          ImageView imageView = new ImageView( getClass().getResource("tiger.jpg").toExternalForm());
            ImageView imageView = new ImageView( "http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg");

            // create circle
            Circle circle = new Circle( 200);
            circle.relocate(200, 100);

            // clip image by circle
            imageView.setClip(circle);

            // non-clip area should be transparent
            SnapshotParameters parameters = new SnapshotParameters();
            parameters.setFill(Color.TRANSPARENT); 

            // new image from clipped image
            WritableImage wim = null;
            wim = imageView.snapshot(parameters, wim);

            // new imageview
            ImageView clippedView = new ImageView( wim);

            // some shadow
            clippedView.setEffect(new DropShadow(15, Color.BLACK));

            clippedView.relocate( 200, 100);

            getChildren().addAll( clippedView);

        }

    }

    // make node draggable
    class DragContext { 
        double x;
        double y; 
    } 

    public void makeDraggable( Node node) {

        final DragContext dragDelta = new DragContext();

        node.setOnMousePressed(mouseEvent -> {

            dragDelta.x = node.getBoundsInParent().getMinX() - mouseEvent.getScreenX();
            dragDelta.y = node.getBoundsInParent().getMinY() - mouseEvent.getScreenY();

        });

        node.setOnMouseDragged(mouseEvent -> node.relocate( mouseEvent.getScreenX() + dragDelta.x, mouseEvent.getScreenY() + dragDelta.y));

    }


}

enter image description here

只需单击脸部并将其拖动即可。

或者您对整个场景进行快照并将其剪辑,以便在新图像中包含所有内容:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class ClipScene extends Application {

    Stage primaryStage;

    @Override
    public void start(Stage primaryStage) {

        this.primaryStage = primaryStage;

        Group root = new Group();

        // background image
//      ImageView imageView = new ImageView( getClass().getResource("tiger.jpg").toExternalForm());
        ImageView imageView = new ImageView( "http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg");

        // some text
        Label label = new Label( "This is a Tiger. Tigers are awesome!");
        label.relocate(20, 400);
        label.setTextFill(Color.RED);
        label.setFont(new Font("Tahoma", 48));

        root.getChildren().addAll( imageView, label);

        Scene scene = new Scene( root, 1024, 768);

        primaryStage.setScene( scene);
        primaryStage.show();

        // pane with clipped area
        CirclePane circlePane = new CirclePane();
        makeDraggable( circlePane);

        root.getChildren().addAll( circlePane);

    }

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


    private class CirclePane extends Pane {

        public CirclePane() {

            WritableImage wim = null;

            // load image
            wim = primaryStage.getScene().snapshot( wim);

            // create imageview
            ImageView imageView = new ImageView( wim);

            // create circle
            Circle circle = new Circle( 200);
            circle.relocate(200, 100);

            // clip image by circle
            imageView.setClip(circle);

            // non-clip area should be transparent
            SnapshotParameters parameters = new SnapshotParameters();
            parameters.setFill(Color.TRANSPARENT); 

            // new image from clipped image
            wim = imageView.snapshot(parameters, wim);

            // new imageview
            ImageView clippedView = new ImageView( wim);

            // some shadow
            clippedView.setEffect(new DropShadow(15, Color.BLACK));

            clippedView.relocate( 200, 100);

            getChildren().addAll( clippedView);

        }

    }

    // make node draggable
    class DragContext { 
        double x;
        double y; 
    } 

    public void makeDraggable( Node node) {

        final DragContext dragDelta = new DragContext();

        node.setOnMousePressed(mouseEvent -> {

            dragDelta.x = node.getBoundsInParent().getMinX() - mouseEvent.getScreenX();
            dragDelta.y = node.getBoundsInParent().getMinY() - mouseEvent.getScreenY();

        });

        node.setOnMouseDragged(mouseEvent -> node.relocate( mouseEvent.getScreenX() + dragDelta.x, mouseEvent.getScreenY() + dragDelta.y));

    }


}

enter image description here

这是背景垂直滚动的动画版本:

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class ClipImage extends Application {

    Stage primaryStage;

    @Override
    public void start(Stage primaryStage) {

        this.primaryStage = primaryStage;

        Group root = new Group();

        // background image
        ImageView imageView = new ImageView( "http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Sunset_2007-1.jpg/640px-Sunset_2007-1.jpg");

        root.getChildren().addAll( imageView);

        Scene scene = new Scene( root, 1024, 768);

        primaryStage.setScene( scene);
        primaryStage.show();

        // pane with clipped area
        CirclePane circlePane = new CirclePane();
        makeDraggable( circlePane);

        root.getChildren().addAll( circlePane);

        AnimationTimer timer = new AnimationTimer() {

            @Override
            public void handle(long now) {
                circlePane.scroll();                
            }

        };
        timer.start();
    }

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


    private class CirclePane extends Pane {

        double y = 0;
        ImageView clippedView;
        ImageView imageView;
        Circle circle;
        SnapshotParameters parameters;
        WritableImage wim = null;

        boolean directionForward = true;

        public CirclePane() {

            imageView = new ImageView( "http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Sunset_2007-1.jpg/640px-Sunset_2007-1.jpg");

            // create circle
            circle = new Circle( 100);
            circle.relocate(200, 100);

            // clip image by circle
            imageView.setClip(circle);

            // non-clip area should be transparent
            parameters = new SnapshotParameters();
            parameters.setFill(Color.TRANSPARENT); 

            // new image from clipped image
            wim = null;
            wim = imageView.snapshot(parameters, wim);

            // new imageview
            clippedView = new ImageView( wim);

            // some shadow
            clippedView.setEffect(new DropShadow(15, Color.BLACK));

            clippedView.relocate( 150, 100);

            getChildren().addAll( clippedView);

        }

        public void scroll() {

            if( directionForward) {
                y++;
                if( y > 100) {
                    directionForward = false;
                }
            } else {
                y--;
                if( y < 0) {
                    directionForward = true;
                }
            }

            circle.relocate(150, 100 + y);
            imageView.setClip(circle);
            wim = imageView.snapshot(parameters, wim);
            clippedView.setImage( wim);
        }

    }

    // make node draggable
    class DragContext { 
        double x;
        double y; 
    } 

    public void makeDraggable( Node node) {

        final DragContext dragDelta = new DragContext();

        node.setOnMousePressed(mouseEvent -> {

            dragDelta.x = node.getBoundsInParent().getMinX() - mouseEvent.getScreenX();
            dragDelta.y = node.getBoundsInParent().getMinY() - mouseEvent.getScreenY();

        });

        node.setOnMouseDragged(mouseEvent -> node.relocate( mouseEvent.getScreenX() + dragDelta.x, mouseEvent.getScreenY() + dragDelta.y));

    }


}

enter image description here

与文本相同,其中场景用于创建imageview和标签的组合快照。

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class ClipScene extends Application {

    Stage primaryStage;

    @Override
    public void start(Stage primaryStage) {

        this.primaryStage = primaryStage;

        Group root = new Group();

        // background image
        ImageView imageView = new ImageView( "http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Sunset_2007-1.jpg/640px-Sunset_2007-1.jpg");

        // some text
        Label label = new Label( "Let the sun shine!");
        label.relocate(180, 220);
        label.setTextFill(Color.YELLOW);
        label.setFont(new Font("Tahoma", 18));

        root.getChildren().addAll( imageView, label);

        Scene scene = new Scene( root, 1024, 768);

        primaryStage.setScene( scene);
        primaryStage.show();

        // pane with clipped area
        CirclePane circlePane = new CirclePane();
        makeDraggable( circlePane);

        root.getChildren().addAll( circlePane);

//      label.setVisible(false);
//      imageView.setVisible(false);

        AnimationTimer timer = new AnimationTimer() {

            @Override
            public void handle(long now) {
                circlePane.scroll();                
            }

        };
        timer.start();
    }

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


    private class CirclePane extends Pane {

        double y = 0;
        ImageView clippedView;
        ImageView imageView;
        Circle circle;
        SnapshotParameters parameters;
        WritableImage wim = null;

        boolean direction = true;

        public CirclePane() {

            WritableImage wim = null;

            // load image
            wim = primaryStage.getScene().snapshot( wim);

            imageView = new ImageView( wim);

            // create circle
            circle = new Circle( 100);
            circle.relocate(200, 100);

            // clip image by circle
            imageView.setClip(circle);

            // non-clip area should be transparent
            parameters = new SnapshotParameters();
            parameters.setFill(Color.TRANSPARENT); 

            // new image from clipped image
            wim = null;
            wim = imageView.snapshot(parameters, wim);

            // new imageview
            clippedView = new ImageView( wim);

            // some shadow
            clippedView.setEffect(new DropShadow(15, Color.BLACK));

            clippedView.relocate( 150, 100);

            getChildren().addAll( clippedView);

        }

        public void scroll() {

            if( direction) {
                y++;
                if( y > 100) {
                    direction = false;
                }
            } else {
                y--;
                if( y < 0) {
                    direction = true;
                }
            }

            circle.relocate(150, 100 + y);
            imageView.setClip(circle);
            wim = imageView.snapshot(parameters, wim);
            clippedView.setImage( wim);
        }

    }

    // make node draggable
    class DragContext { 
        double x;
        double y; 
    } 

    public void makeDraggable( Node node) {

        final DragContext dragDelta = new DragContext();

        node.setOnMousePressed(mouseEvent -> {

            dragDelta.x = node.getBoundsInParent().getMinX() - mouseEvent.getScreenX();
            dragDelta.y = node.getBoundsInParent().getMinY() - mouseEvent.getScreenY();

        });

        node.setOnMouseDragged(mouseEvent -> node.relocate( mouseEvent.getScreenX() + dragDelta.x, mouseEvent.getScreenY() + dragDelta.y));

    }


}

enter image description here

这里全部合并,动画日落在屏幕外“渲染”,即我们使用窗格拍摄快照,而不是场景:

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class ClipOffScreen extends Application {

    @Override
    public void start(Stage primaryStage) {

        Group root = new Group();

        // background image
        ImageView imageView = new ImageView( "http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/800px-Siberischer_tiger_de_edit02.jpg");

        // some text
        Label label = new Label( "This is a Tiger. Tigers are awesome!");
        label.relocate(20, 400);
        label.setTextFill(Color.RED);
        label.setFont(new Font("Tahoma", 48));

        root.getChildren().addAll( imageView, label);

        Scene scene = new Scene( root, 1024, 768);

        primaryStage.setScene( scene);
        primaryStage.show();

        // pane with clipped area
        CirclePane circlePane = new CirclePane();
        makeDraggable( circlePane);

        root.getChildren().addAll( circlePane);

        AnimationTimer timer = new AnimationTimer() {

            @Override
            public void handle(long now) {
                circlePane.scroll();                
            }

        };
        timer.start();
    }

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


    private class CirclePane extends Pane {

        double y = 0;
        ImageView clippedView;
        ImageView imageView;
        Circle circle;
        SnapshotParameters parameters;
        WritableImage wim = null;

        boolean direction = true;

        public CirclePane() {

            Pane offScreenPane = new Pane();

            // background image
            ImageView imageView2 = new ImageView( "http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Sunset_2007-1.jpg/640px-Sunset_2007-1.jpg");

            // some text
            Text text = new Text( "Let the sun shine!");
            text.relocate(180, 220);
            text.setFill(Color.YELLOW);
            text.setFont(new Font("Tahoma", 18));

            offScreenPane.getChildren().addAll( imageView2, text);

            // non-clip area should be transparent
            parameters = new SnapshotParameters();
            parameters.setFill(Color.TRANSPARENT); 

            WritableImage wim = null;

            // load image
            wim = offScreenPane.snapshot( parameters, wim);

            imageView = new ImageView( wim);

            // create circle
            circle = new Circle( 100);
            circle.relocate(200, 100);

            // clip image by circle
            imageView.setClip(circle);



            // new image from clipped image
            wim = null;
            wim = imageView.snapshot(parameters, wim);

            // new imageview
            clippedView = new ImageView( wim);

            // some shadow
            clippedView.setEffect(new DropShadow(15, Color.BLACK));

            clippedView.relocate( 150, 100);

            getChildren().addAll( clippedView);

        }

        public void scroll() {

            if( direction) {
                y++;
                if( y > 100) {
                    direction = false;
                }
            } else {
                y--;
                if( y < 0) {
                    direction = true;
                }
            }

            circle.relocate(150, 100 + y);
            imageView.setClip(circle);
            wim = imageView.snapshot(parameters, wim);
            clippedView.setImage( wim);
        }

    }

    // make node draggable
    class DragContext { 
        double x;
        double y; 
    } 

    public void makeDraggable( Node node) {

        final DragContext dragDelta = new DragContext();

        node.setOnMousePressed(mouseEvent -> {

            dragDelta.x = node.getBoundsInParent().getMinX() - mouseEvent.getScreenX();
            dragDelta.y = node.getBoundsInParent().getMinY() - mouseEvent.getScreenY();

        });

        node.setOnMouseDragged(mouseEvent -> node.relocate( mouseEvent.getScreenX() + dragDelta.x, mouseEvent.getScreenY() + dragDelta.y));

    }


}

诀窍是使用Text而不是Label,因为如果Label不可见,它将被隐藏。我想这是某种JavaFX内部优化。

enter image description here