动态更改JavaFX css属性

时间:2018-05-27 13:40:07

标签: java css javafx

在我的FXML中,我有一个简单的滑块:

<Slider fx:id="timeSlider" showTickLabels="true" GridPane.rowIndex="3" GridPane.columnIndex="0" GridPane.columnSpan="4"/>

此滑块是我正在编写的桌面音乐应用程序的一部分,它表示歌曲播放的距离。我写了一个改变事件,每当歌曲时间改变时调用,这成功完成了旋钮/拇指的滑动。

现在,当旋钮向下滑动时,我还试图将左侧部分(已播放)的蓝色和右侧部分(尚未播放)的颜色设为白色。如果我将这一行硬编码到我的CSS中,我可以在50%的标记处实现蓝/白的淡化。

.slider .track {-fx-background-color: linear-gradient(to right, #90C7E0 50%, white 50%);}

但是,根据我在歌曲中的位置,我需要动态。我编写了以下代码,但似乎无法应用CSS样式

song.getMediaPlayer().currentTimeProperty().addListener(new ChangeListener<Duration>() {
        @Override
        public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
            if (newValue != null && timeSlider != null) {
                timeSlider.setValue(newValue.toSeconds());
                double percentage = (newValue.toSeconds()/song.getDuration())*100;
                String css = ".slider .track{-fx-background-color: linear-gradient(to right, #90C7E0 " +
                 percentage + "%, white " + percentage + "%);}";
                timeSlider.getStyleClass().add(css);
            }
        }
    });

我认为这与我如何将CSS添加为样式有关,因为即使添加简单的非动态样式也行不通。我没有错,所以我不确定我做错了什么。

任何帮助都表示赞赏,并且还有更好的方法来实现这一目标。谢谢!

2 个答案:

答案 0 :(得分:2)

方法getStyleClass()返回与节点关联的CSS类名列表。这些类名用于确定外部CSS文件中的哪些规则应用于节点。你不能在这里传递CSS选择器和规则。

而是编写一个外部CSS文件,其中包含轨道背景颜色的规则。您可以使用&#34;查找颜色&#34;在这里,它基本上像一个&#34; CSS变量&#34;。定义&#34;查找颜色&#34;对于滑块,并在轨道规则中使用它来设置背景颜色:

style.css

.slider {
    -track-color: white ;
}
.slider .track {
    -fx-background-color: -track-color ;
}

现在,在Java代码中,您可以通过调用滑块上的setStyle("-track-color: /* someColor */")来更新查找颜色的值。这是一个简单的例子:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class SliderTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Slider slider = new Slider();
        slider.valueProperty().addListener((obs, oldValue, newValue) -> {
            double percentage = 100.0 * (newValue.doubleValue() - slider.getMin()) / (slider.getMax() - slider.getMin());
            slider.setStyle("-track-color: linear-gradient(to right, #90C7E0 " + percentage+"%, white "+percentage+("%);"));
        });
        StackPane root = new StackPane(slider);
        root.setPadding(new Insets(20));
        Scene scene = new Scene(root);
        scene.getStylesheets().add("style.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

在你的应用程序中,你可以使用媒体播放器的当前时间(或者只是在滑块的value属性上注册一个监听器,因为它也会改变)。

答案 1 :(得分:0)

在评论中的帮助下,我提出了一个解决方案,

.getStyleClass.add(...)没有按照我原先的想法做,我需要使用.setStyle(...),但是,我需要在滑块TRACK上设置样式而不是滑块本身。这是我现在的代码......

public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
            if (newValue != null && timeSlider != null) {
                double percentage = (newValue.toSeconds()/song.getDuration())*100;
                String cssValue = "-fx-background-color: linear-gradient(to right, #90C7E0 " +
                 percentage + "%, white " + percentage + "%)";
                StackPane sliderTrack = (StackPane) timeSlider.lookup(".track");
                sliderTrack.setStyle(cssValue);
                timeSlider.setValue(newValue.toSeconds());
            }
        }