这是一个很难解释的情况,我会尽力而为。
我需要做一个圆形窗格或一个隐藏圆圈区域之外的元素(节点)部分的场景。我的意思是,我不想只隐藏外面的区域。就像一个“.setClip”。我无法使用最后一种方法,因为项目是动画,当我移动节点时,剪辑也会移动。
当文本出现时,这就是我想要做的。
这是我项目中的图片。红色标记显示问题。
谢谢!
PD:这是DocumentController Link
答案 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));
}
}
只需单击脸部并将其拖动即可。
或者您对整个场景进行快照并将其剪辑,以便在新图像中包含所有内容:
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));
}
}
这是背景垂直滚动的动画版本:
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));
}
}
与文本相同,其中场景用于创建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));
}
}
这里全部合并,动画日落在屏幕外“渲染”,即我们使用窗格拍摄快照,而不是场景:
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内部优化。