JavaFX 反向裁剪和使用文本的裁剪?
JavaFX inverse-clipping and clipping using text?
到目前为止,关于 JavaFX 中的裁剪,我能找到的所有内容都是 Node.setClip(Node value)
方法。这会强制节点仅在给定节点的边界内呈现。我想做相反的事情——根据第二个节点的形状,特别是文本,切掉一部分节点。在(大部分)伪代码中:
Rectangle rect = new Rectangle(0, 0, 160, 90);
Label cutOutText = new Label("YAY");
rect.setFill(Color.RED);
rect.setInverseClip(cutOutText);
这将导致(在白色背景上)...
另一个例子:
据我所知,没有内置的方法。但是,这是您尝试使用形状实现的示例:
package application;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.effect.InnerShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(final Stage primaryStage) {
final StackPane root = new StackPane();
final ProgressBar bar = new ProgressBar();
final Image image = new Image( "https://farm8.staticflickr.com/7036/6952932649_3fc1cfeb8a_o_d.jpg", true );
final ImageView imageView = new ImageView( image );
final Text clip = new Text( "JavaFx" );
final Scene scene = new Scene( root );
root.setStyle( "-fx-background: pink;" );
root.setEffect( new InnerShadow() );
bar.prefWidthProperty().bind( root.widthProperty() );
bar.visibleProperty().bind( Bindings.notEqual( 1, image.progressProperty() ) );
bar.progressProperty().bind( image.progressProperty() );
imageView.setFitWidth( 800 );
imageView.setFitHeight( 600 );
clip.setFont( Font.font( 144.0 ) );
clip.setX( 400 - clip.getBoundsInLocal().getWidth() / 2 );
clip.setY( 400 - clip.getBoundsInLocal().getHeight() / 2 );
setInverseClip( imageView, clip );
root.getChildren().add( bar );
root.getChildren().add( imageView );
primaryStage.setScene( scene );
primaryStage.show();
}
private void setInverseClip( final Node node, final Shape clip ) {
final Rectangle inverse = new Rectangle();
inverse.setWidth( node.getLayoutBounds().getWidth() );
inverse.setHeight( node.getLayoutBounds().getHeight() );
node.setClip( Shape.subtract( inverse, clip ) );
}
public static void main(final String[] args) {
launch(args);
}
}
在目标节点上叠加一个同样大小的矩形,减去原来的裁剪节点,将新创建的形状作为裁剪到目标节点。
这是一个适用于常规 Label
的版本。只需将下面的侦听器添加到您的标签中,并确保 Label
文本是透明的,并且有背景。
CSS:
.content-rating, .adult-rating {
-fx-background-color: rgb(213, 222, 255);
-fx-background-radius: 10px;
-fx-text-fill: transparent;
}
Java代码:
InvalidationListener listener = (obs) -> {
Text text = new Text();
text.setFont(label.getFont());
text.setText(label.getText());
Bounds b = label.getLayoutBounds();
Insets insets = label.getInsets();
Region.layoutInArea(text, b.getMinX(), b.getMinY(), b.getWidth(), b.getHeight(), 0, insets, false, false, label.getAlignment().getHpos(), label.getAlignment().getVpos(), true);
Rectangle r = new Rectangle(-insets.getLeft(), -insets.getTop(), b.getWidth() + insets.getRight(), b.getHeight() + insets.getBottom());
label.setClip(Shape.subtract(r, text));
};
label.layoutBoundsProperty().addListener(listener);
它在 JavaFX 应用程序中的外观示例:
到目前为止,关于 JavaFX 中的裁剪,我能找到的所有内容都是 Node.setClip(Node value)
方法。这会强制节点仅在给定节点的边界内呈现。我想做相反的事情——根据第二个节点的形状,特别是文本,切掉一部分节点。在(大部分)伪代码中:
Rectangle rect = new Rectangle(0, 0, 160, 90);
Label cutOutText = new Label("YAY");
rect.setFill(Color.RED);
rect.setInverseClip(cutOutText);
这将导致(在白色背景上)...
另一个例子:
据我所知,没有内置的方法。但是,这是您尝试使用形状实现的示例:
package application;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.effect.InnerShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(final Stage primaryStage) {
final StackPane root = new StackPane();
final ProgressBar bar = new ProgressBar();
final Image image = new Image( "https://farm8.staticflickr.com/7036/6952932649_3fc1cfeb8a_o_d.jpg", true );
final ImageView imageView = new ImageView( image );
final Text clip = new Text( "JavaFx" );
final Scene scene = new Scene( root );
root.setStyle( "-fx-background: pink;" );
root.setEffect( new InnerShadow() );
bar.prefWidthProperty().bind( root.widthProperty() );
bar.visibleProperty().bind( Bindings.notEqual( 1, image.progressProperty() ) );
bar.progressProperty().bind( image.progressProperty() );
imageView.setFitWidth( 800 );
imageView.setFitHeight( 600 );
clip.setFont( Font.font( 144.0 ) );
clip.setX( 400 - clip.getBoundsInLocal().getWidth() / 2 );
clip.setY( 400 - clip.getBoundsInLocal().getHeight() / 2 );
setInverseClip( imageView, clip );
root.getChildren().add( bar );
root.getChildren().add( imageView );
primaryStage.setScene( scene );
primaryStage.show();
}
private void setInverseClip( final Node node, final Shape clip ) {
final Rectangle inverse = new Rectangle();
inverse.setWidth( node.getLayoutBounds().getWidth() );
inverse.setHeight( node.getLayoutBounds().getHeight() );
node.setClip( Shape.subtract( inverse, clip ) );
}
public static void main(final String[] args) {
launch(args);
}
}
在目标节点上叠加一个同样大小的矩形,减去原来的裁剪节点,将新创建的形状作为裁剪到目标节点。
这是一个适用于常规 Label
的版本。只需将下面的侦听器添加到您的标签中,并确保 Label
文本是透明的,并且有背景。
CSS:
.content-rating, .adult-rating {
-fx-background-color: rgb(213, 222, 255);
-fx-background-radius: 10px;
-fx-text-fill: transparent;
}
Java代码:
InvalidationListener listener = (obs) -> {
Text text = new Text();
text.setFont(label.getFont());
text.setText(label.getText());
Bounds b = label.getLayoutBounds();
Insets insets = label.getInsets();
Region.layoutInArea(text, b.getMinX(), b.getMinY(), b.getWidth(), b.getHeight(), 0, insets, false, false, label.getAlignment().getHpos(), label.getAlignment().getVpos(), true);
Rectangle r = new Rectangle(-insets.getLeft(), -insets.getTop(), b.getWidth() + insets.getRight(), b.getHeight() + insets.getBottom());
label.setClip(Shape.subtract(r, text));
};
label.layoutBoundsProperty().addListener(listener);
它在 JavaFX 应用程序中的外观示例: