【问题标题】:is it possible to make a percentage of a linear gradient in javafx?是否可以在 javafx 中制作一定百分比的线性渐变?
【发布时间】:2021-12-18 19:58:36
【问题描述】:

考虑以下线性渐变“A”。通常,如果您将该笔刷指定为矩形的背景,它会用整个渐变填充整个区域,而不管大小。 (见“B”)。

我们试图说“对于这个特定的控件,只使用画笔的前 xx% 进行填充”,因此我们可以实现基于百分比的渐变填充,就像在“C”中一样。

【问题讨论】:

  • 我不认为您可以纯粹使用LinearGradient(以编程方式或CSS)来做到这一点。您可以使用剪辑做一些事情(请参阅Node.clip 属性)。如果您将带有渐变的节点保持在原始大小,然后将其裁剪为宽度的一半,那么我相信您只会看到 50% 的渐变。但也许有更好的方法。这也可能是一个XY 问题。如果您解释了为什么要这样做,那么也许可以提出替代方案。
  • Style a progress bar to your satisfaction。如果您按照 Slaw 的建议编辑问题,或许可以提供更有针对性的答案。
  • 为您尝试的解决方案提供源代码(Java 和 css)。
  • 不确定您所说的“50%”宽度是什么意思。 50% 什么?宽度有变化吗?图片 D 提出了一个解决方案:有一个“全宽”矩形并将其剪掉。

标签: javafx


【解决方案1】:

有很多方法可以解决这个问题。我提出了三个示例解决方案:

  1. 使用固定宽度渐变。
  2. 使用剪辑。
  3. 使用插值器。

所有提出的解决方案都采用了固定大小的简单方法。如果您想要一个动态大小,您可以在底层矩形宽度和高度上使用适当的侦听器或绑定来实现它,以更新相关的剪辑或渐变设置。

使用固定宽度渐变

渐变是在固定坐标而不是比例坐标中定义的(停靠点仍然是比例的)。矩形本身的宽度是总宽度的百分比,线性渐变是为整个宽度定义的。任何不适合矩形的渐变部分都不会显示,从而给出所需的结果。

LinearGradient gradient = new LinearGradient(
        0, 0, W, 0,
        false,
        CycleMethod.NO_CYCLE,
        new Stop(0, Color.LAWNGREEN),
        new Stop(.5, Color.YELLOW),
        new Stop(1, Color.ORANGERED)
);

return new Rectangle(W * visiblePortion, H, gradient);

使用剪辑

在这里,我们将剪辑应用于具有渐变的矩形,因此只有矩形的一部分是可见的。

Rectangle rect = new Rectangle(W, H);
rect.setStyle("-fx-fill: linear-gradient(to right, lawngreen, yellow, orangered);");

Rectangle clip = new Rectangle(W * visiblePortion, H);
rect.setClip(clip);

该示例使用 css 定义渐变,但如果您愿意,您可以使用 LinearGradient API 在 Java 代码中定义它。

使用插值器

如果您想在没有所需样式的剪辑的情况下进行比例渐变,则需要调整渐变中使用的颜色和色标以匹配所需的百分比显示(使用您为计算创建的算法)。

双色平滑渐变很简单,但一般的解决方案很困难,因为具有多个停止的渐变定义变得复杂。我这里只提供一种双色平滑渐变的解决方案。

该实现使用Color.interpolate() 函数(作为 Color 实现 Interpolatable)来计算渐变的停止颜色。

图像看起来与基于剪辑的解决方案不同,因为基于剪辑的解决方案使用了更复杂的 3 级渐变,而该解决方案仅使用了简单的两种颜色渐变。

这个实现的关键是使用插值器定义梯度:

LinearGradient gradient = new LinearGradient(
        0, 0, 1, 0,
        true,
        CycleMethod.NO_CYCLE,
        new Stop(0, Color.GREEN),
        new Stop(1, Color.GREEN.interpolate(Color.RED, visiblePortion))
);
return new Rectangle(W * visiblePortion, H, gradient);

使用进度条

图像看起来很像一个进度条。如果合适,您可以调查styling a progress bar。我不会在这里为渐变样式的进度条提供解决方案。如果这是您想要的,请专门提出一个新问题。

示例应用程序

import javafx.application.Application;
import javafx.geometry.*;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.paint.*;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

import java.util.function.Function;

public class GradientDemo extends Application {
    private static final double W = 500;
    private static final double H = 10;
    private static final double STEP = 0.2;

    @Override
    public void start(Stage stage) {
        final VBox layout = new VBox(10);
        layout.setAlignment(Pos.TOP_LEFT);
        layout.setPadding(new Insets(10));

        addGradients(layout, "fixedWidthTriColorGradient", this::fixedWidthTriColorGradient);
        addGradients(layout, "clippedTriColorGradient", this::clippedTriColorGradient);
        addGradients(layout, "interpolatedTwoColorGradient", this::interpolatedTwoColorGradient);

        stage.setScene(new Scene(layout));
        stage.show();
    }

    private void addGradients(
            VBox layout,
            String gradientName,
            Function<Double, Node> gradientFactory
    ) {
        Label label = new Label(gradientName);
        label.setPadding(new Insets(5, 0, 0, 0));
        layout.getChildren().addAll(
                label
        );
        for (double f = STEP; f <= 1.0; f += STEP) {
            layout.getChildren().addAll(gradientFactory.apply(f));
        }
    }

    public Rectangle fixedWidthTriColorGradient(double visiblePortion) {
        LinearGradient gradient = new LinearGradient(
                0, 0, W, 0,
                false,
                CycleMethod.NO_CYCLE,
                new Stop(0, Color.LAWNGREEN),
                new Stop(.5, Color.YELLOW),
                new Stop(1, Color.ORANGERED)
        );

        return new Rectangle(W * visiblePortion, H, gradient);
    }

    public Rectangle clippedTriColorGradient(double visiblePortion) {
        Rectangle rect = new Rectangle(W, H);
        rect.setStyle("-fx-fill: linear-gradient(to right, lawngreen, yellow, orangered);");

        Rectangle clip = new Rectangle(W * visiblePortion, H);
        rect.setClip(clip);

        return rect;
    }

    public Rectangle interpolatedTwoColorGradient(double visiblePortion) {
        LinearGradient gradient = new LinearGradient(
                0, 0, 1, 0,
                true,
                CycleMethod.NO_CYCLE,
                new Stop(0, Color.GREEN),
                new Stop(1, Color.GREEN.interpolate(Color.RED, visiblePortion))
        );

        return new Rectangle(W * visiblePortion, H, gradient);
    }

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

【讨论】:

    猜你喜欢
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    相关资源
    最近更新 更多