Поведение линейного градиента Javafx - PullRequest
3 голосов
/ 04 апреля 2019

Повтор линейного градиента Javafx, кажется, отражает цвета, а не повтор.

Я написал простое приложение, чтобы показать, что я вижу при использовании линейного градиента с повторением для создания полосатого шаблона в моем приложении на пользовательском узле (StackPane). В моем приложении это добавляется как наложение на XYChart, и их высота меняется. Использование Rectangle не сработало, поэтому я использую Stackpane и задаю для него стиль, а не создаю LinearGradient программно. Список цветов является динамическим и различается по размеру в приложении. Проблема заключается в том, как линейный градиент переворачивает список и отображает цвета при каждом повторении, а не только при повторении.

Эта ссылка описывает аналогичную проблему, но просто добавление бесконечных остановок кажется беспорядочным решением для моей проблемы, было бы намного лучше добавить цвета один раз и повторить.

повторение линейного градиента на CSS для javafx

java.util.List;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            List<Color> colors = Arrays.asList( Color.RED,Color.BLUE,Color.YELLOW,Color.GREEN);

            StackPane stackPane = new StackPane();

            stackPane.setStyle(getLinearGradientStyle(colors));
            root.setCenter(stackPane);
            Scene scene = new Scene(root, 400, 400);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getLinearGradientStyle(List<Color> colors) {
        StringBuilder stringBuilder = new StringBuilder("-fx-background-color: linear-gradient(from 0px 0px to 10px 10px, repeat,");
        for (int i = 0; i < colors.size(); i++) {
            stringBuilder.append("rgb(")
                    .append((int) (colors.get(i).getRed() * 255)).append(",")
                    .append((int) (colors.get(i).getGreen() * 255)).append(",")
                    .append((int) (colors.get(i).getBlue() * 255))
                    .append(")")
                    .append(" ").append(getPercentage(i+1, colors.size()+1) );
            if (i < colors.size() - 1) {
                stringBuilder.append(",");
            }
        }
        stringBuilder.append(");");
        System.out.println("Main.getLinearGradientStyle():"+stringBuilder);
        return stringBuilder.toString();
    }

    private String getPercentage(float i, int size) {
        return  (((1.0f / size) * 100 )*i)+ "%";
    }


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

}

Вот пример CSS3 с использованием повторяющегося линейного градиента:

https://tympanus.net/codrops/css_reference/repeating-linear-gradient/

прокрутите вниз до следующего текста: создаст полосатый фон, где каждый линейный градиент представляет собой градиент из трех полос, повторяющийся бесконечно (это пример)

В моем примере используется диагональный шаблон, который мне нужен, но в приведенном выше примере показано, что я хотел бы видеть в терминах сплошных повторяющихся цветов без отражения в обычном CSS.

Спасибо за любую помощь

1 Ответ

5 голосов
/ 04 апреля 2019

Это похоже на ошибку.Если вы запустите следующий пример (перенес CSS в файл):

Main.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Region;
import javafx.stage.Stage;


public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        Region region = new Region();
        region.backgroundProperty().addListener((obs, ov, nv) ->
                System.out.println(nv.getFills().get(0).getFill()));

        Scene scene = new Scene(region, 500, 300);
        scene.getStylesheets().add("Main.css");

        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

Main.css

.root {
    -fx-background-color: linear-gradient(from 0px 0px to 10px 10px, repeat, red 20%, blue 40%, yellow 60%, green 80%);
}

Вы увидите следующее распечатанное:

linear-gradient(from 0.0px 0.0px to 10.0px 10.0px, reflect, 0xff0000ff 0.0%, 0xff0000ff 20.0%, 0x0000ffff 40.0%, 0xffff00ff 60.0%, 0x008000ff 80.0%, 0x008000ff 100.0%)

Как видите, несмотря на использование «repeat» в CSS, созданный LinearGradient использует «отражение».

Вероятно, вы ничего не можете сделать с этой ошибкой самостоятельно, но если вы не возражаете против установки фона в коде (или, возможно, даже FXML), то следующее должно сделать то, что вы хотите:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.stage.Stage;


public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        LinearGradient gradient = new LinearGradient(0, 0, 10, 10, false, CycleMethod.REPEAT,
                new Stop(0.2, Color.RED),
                new Stop(0.4, Color.BLUE),
                new Stop(0.6, Color.YELLOW),
                new Stop(0.8, Color.GREEN)
        );

        Region region = new Region();
        region.setBackground(new Background(new BackgroundFill(gradient, null, null)));

        Scene scene = new Scene(region, 500, 300);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

Вы можете переместить создание LinearGradient в метод, который принимает произвольное число Color с, точно так же, как вы делаете в настоящее время.


Если вам интересно, я считаю, что ошибка находится в javafx.css.CssParser вокруг строки 1872 (в JavaFX 12):

CycleMethod cycleMethod = CycleMethod.NO_CYCLE;
if ("reflect".equalsIgnoreCase(arg.token.getText())) {
    cycleMethod = CycleMethod.REFLECT;
    prev = arg;
    arg = arg.nextArg;
} else if ("repeat".equalsIgnoreCase(arg.token.getText())) {
    cycleMethod = CycleMethod.REFLECT;
    prev = arg;
    arg = arg.nextArg;
}

Как видите, она ошибочно устанавливает CycleMethod вREFLECT когда текст равен "repeat ".

Подано сообщение об ошибке: JDK-8222222 (GitHub # 437 ). Исправлена ​​версия: опеnjfx13 .

...