На самом деле вы ничего не можете с этим поделать, но уменьшите количество повторений в коде.(Вы не сможете ничего интерполировать, поскольку при каждом обновлении следующий цвет выбирается случайным образом.)
Вы должны использовать один и тот же код для всех цветовых каналов:
/**
* Class containing logic for a single color channel.
*/
private class AnimatedChannel {
private boolean increment = true;
private int value;
AnimatedChannel(int value) {
this.value = value;
}
/**
* Changes channel by random amount in [1, 3] keeping it in range [155, 255]
*/
private void update() {
int delta = getRandomNumber();
if (increment) {
value += delta;
if (value > 0xFF) {
value = (2 * 0xFF) - value; // v = max - (v - max)
increment = false;
}
} else {
value -= delta;
if (value < 155) {
value = (2 * 155) - value; // v = min + (min - v)
increment = true;
}
}
}
}
private final Random random = new Random();
private int getRandomNumber() {
return random.nextInt(3 - 1) + 1;
}
private final AnimatedChannel bottomRed = new AnimatedChannel(171);
private final AnimatedChannel bottomGreen = new AnimatedChannel(186);
private final AnimatedChannel bottomBlue = new AnimatedChannel(171);
private final AnimatedChannel topRed = new AnimatedChannel(0xFF);
private final AnimatedChannel topGreen = new AnimatedChannel(0xFF);
private final AnimatedChannel topBlue = new AnimatedChannel(0xFF);
private final AnimatedChannel[] channels = new AnimatedChannel[] {
bottomRed,
bottomGreen,
bottomBlue,
topRed,
topGreen,
topBlue
};
@Override
protected Void call() throws Exception {
Timeline backgroundAnimator = new Timeline(new KeyFrame(Duration.millis(200), event -> {
for (AnimatedChannel channel : channels) {
channel.update();
}
backgroundPane.setBackground(new Background(new BackgroundFill(
new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
new Stop(0, channelsToColor(topRed, topGreen, topBlue)),
new Stop(1, channelsToColor(bottomRed, bottomGreen, bottomBlue))),
CornerRadii.EMPTY,
Insets.EMPTY)));
}));
backgroundAnimator.setCycleCount(Timeline.INDEFINITE);
backgroundAnimator.play();
return null;
}
private static Color channelsToColor(AnimatedChannel red, AnimatedChannel green, AnimatedChannel blue) {
return Color.rgb(red.value, green.value, blue.value);
}
Этот код не намного короче вашего кода, но его легче поддерживать.Если вы хотите изменить логику обновления каналов, вам нужно настроить только 1 метод вместо 6 методов.Кроме того, это освобождает JavaFX от необходимости разбора встроенного CSS при каждом обновлении.
Примечание:
Похоже, вы расширяете Task<Void>
или что-то подобное, связанное с параллелизмомучебный класс.В этом нет необходимости, поскольку Timeline.play
не является длительной операцией, а просто запускает повторное выполнение логики (в данном случае EventHandler<ActionEvent>
) в потоке приложения в более позднее время.