从窗格中心填充 JavaFX 形状

问题描述 投票:0回答:1

我有一个使用 JavaFX 中的路径创建的自定义形状。我想从屏幕中心开始填充形状,在T秒内填满。

我目前有一个简单的版本,使用从底部填充的矩形,但我不知道如何将其应用于通用形状并从屏幕中心填充它。

这是我当前拥有的示例,其中颜色从形状的底部填充。 (红色箭头标记)

我宁愿将形状从窗格中的中心点(用红点估计)填充到绿色箭头。

package com.example.javafx21;

import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import javafx.util.Duration;

public class HelloApplication extends Application {
    @Override
    public void start(Stage primaryStage) {

        Pane pane = new Pane();

        StackPane stackPane = new StackPane();
        stackPane.setLayoutX(50);
        stackPane.setLayoutY(50);

        Rectangle outlineRect = new Rectangle(100, 100);
        outlineRect.setStroke(Color.BLACK);
        outlineRect.setFill(Color.TRANSPARENT);


        Rectangle fillRect = new Rectangle(100, 100);
        fillRect.setFill(Color.BLUE);


        Rectangle maskRect = new Rectangle(100, 100);
        maskRect.setFill(Color.WHITE);
        maskRect.yProperty().bind(fillRect.yProperty().add(fillRect.heightProperty()));
        fillRect.setClip(maskRect);

        stackPane.getChildren().addAll(fillRect, outlineRect);

        Button button = new Button("Fill Rectangle");
        button.setLayoutX(75);
        button.setLayoutY(250);


        pane.getChildren().addAll(stackPane, button);


        TranslateTransition transition = new TranslateTransition(Duration.seconds(2), maskRect);
        transition.setFromY(0);
        transition.setFromX(0);
        transition.setToY(-fillRect.getHeight());
//        transition.setToX(-fillRect.getWidth());
        transition.setCycleCount(1);
        transition.setAutoReverse(false);


        button.setOnAction(e -> transition.play());

        pane.setOnMouseClicked(mouseEvent -> {

            System.out.println("mouse X = " + mouseEvent.getX() + " Mouse Y = " + mouseEvent.getY());
        });

        Scene scene = new Scene(pane, 300, 300);
        primaryStage.setTitle("Rectangle Fill Transition");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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


javafx geometry shapes
1个回答
0
投票

考虑使用

LinearGradient
进行填充。给定要填充的矩形的一定比例
prop
,您可以在线性渐变中使用以下色标:

new Stop(0, Color.BLUE),
new Stop(prop, Color.BLUE),
new Stop(prop, Color.WHITE),
new Stop(1, Color.WHITE)

效果不会像这样创建“渐变”,而是在

BLUE
的值处从
WHITE
prop
的急剧过渡。因此,当
prop
0
时,矩形将全部为
WHITE
,而当
prop
1
时,矩形将全部为
BLUE

您可以根据要求进行对角填充,方法是制作

startX=1
startY=1
endX=0
endY=0
并使用比例线性渐变。

最后,您需要对渐变进行动画处理。您可以通过将比例定义为

DoubleProperty
并使用
Timeline
对其值进行动画处理,然后使用 JavaFX 19 中引入的
map
方法将其值映射到适当的线性渐变来实现此目的。

这是全部内容:

import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; import javafx.application.Application; import javafx.beans.property.DoubleProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.paint.CycleMethod; import javafx.scene.paint.LinearGradient; import javafx.scene.paint.Stop; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import javafx.util.Duration; public class HelloApplication extends Application { @Override public void start(Stage primaryStage) { Pane pane = new Pane(); StackPane stackPane = new StackPane(); stackPane.setLayoutX(50); stackPane.setLayoutY(50); Rectangle outlineRect = new Rectangle(100, 100); outlineRect.setStroke(Color.BLACK); outlineRect.setFill(Color.TRANSPARENT); DoubleProperty fillProportion = new SimpleDoubleProperty(0); Rectangle fillRect = new Rectangle(100, 100); // fillRect.setFill(Color.BLUE); fillRect.fillProperty().bind(fillProportion.map(prop -> new LinearGradient(1, 1, 0, 0, true, CycleMethod.NO_CYCLE, new Stop(0, Color.BLUE), new Stop(prop.doubleValue(), Color.BLUE), new Stop(prop.doubleValue(), Color.WHITE), new Stop(1, Color.WHITE) ) )); // Rectangle maskRect = new Rectangle(100, 100); // maskRect.setFill(Color.WHITE); // maskRect.yProperty().bind(fillRect.yProperty().add(fillRect.heightProperty())); // fillRect.setClip(maskRect); stackPane.getChildren().addAll(fillRect, outlineRect); Button button = new Button("Fill Rectangle"); button.setLayoutX(75); button.setLayoutY(250); pane.getChildren().addAll(stackPane, button); // TranslateTransition transition = new TranslateTransition(Duration.seconds(2), maskRect); // transition.setFromY(0); // transition.setFromX(0); // transition.setToY(-fillRect.getHeight()); //// transition.setToX(-fillRect.getWidth()); // transition.setCycleCount(1); // transition.setAutoReverse(false); Timeline transition = new Timeline( new KeyFrame(Duration.ZERO, new KeyValue(fillProportion, 0)), new KeyFrame(Duration.seconds(2), new KeyValue(fillProportion, 1)) ); button.setOnAction(e -> transition.play()); pane.setOnMouseClicked(mouseEvent -> { System.out.println("mouse X = " + mouseEvent.getX() + " Mouse Y = " + mouseEvent.getY()); }); Scene scene = new Scene(pane, 300, 300); primaryStage.setTitle("Rectangle Fill Transition"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
    
© www.soinside.com 2019 - 2024. All rights reserved.