JavaFX反向裁剪和使用文本进行裁剪?

5

到目前为止,我在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);

这将在白色背景下产生以下结果:...
另一个例子:
请参考以下图片:The resulting rectangle, with punched-out text. 请参考以下图片:enter image description here
2个回答

3
据我所知,目前没有内置的方法可以实现这一点。但是,以下是使用Shapes实现您尝试实现的示例:
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);
    }

}

它通过一个与目标节点相同大小的矩形覆盖目标节点,从中减去原始剪辑节点,并使用新创建的形状作为目标节点的剪辑。


2
谢谢!对于任何和我一样想知道的人,只需查找javafx.scene.Shape.subtract(Shape 1, Shape 2)。它会在从第一个形状中剪切出第二个形状后返回一个新节点。 - Sam Claus

0
这是一个适用于常规 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应用程序中的示例:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接