You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX中通过CSS初始化的Slider刻度标记隐藏后消失

JavaFX Slider CSS配置刻度标记隐藏后消失问题

问题现象

通过代码为JavaFX Slider添加CSS样式类:

slider.getStyleClass().add("slider-style");

首次打开窗口时,CSS配置的Slider正常显示刻度标记;但关闭窗口再重新打开后,刻度标记会消失。

示例中包含两个Slider:

  • 一个通过Java API直接设置属性,窗口隐藏再显示后一切正常;
  • 另一个通过CSS配置属性,窗口隐藏再显示后刻度标记消失。

复现代码

sample.css

.slider-style {
    -fx-show-tick-marks: true;
    -fx-snap-to-ticks: true;
    -fx-major-tick-unit: 5;
    -fx-minor-tick-count: 5;
}

CssExample.java

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.io.IOException;
import java.net.URL;

/**
 * 演示JavaFX中通过CSS配置的Slider仅首次显示时展示刻度标记,隐藏后再显示则刻度永久消失的问题
 */
public class CssExample extends Application {
 
    @Override
    public void start(Stage stage) throws InterruptedException, IOException {
        Group root = new Group();
        Scene scene = new Scene(root, 400, 200);
        stage.setScene(scene);
        stage.setTitle("Slider Sample");
        scene.setFill(Color.BLACK);

        GridPane grid = new GridPane();
        grid.setPadding(new Insets(10, 10, 10, 10));
        grid.setVgap(10);
        grid.setHgap(70);

        scene.setRoot(grid);
        int rowNumber = 1;

        Label directLabel = new Label("通过API直接配置的Slider");
        GridPane.setConstraints(directLabel, 1, rowNumber++);
        grid.getChildren().add(directLabel);

        Slider directSlider = new Slider();
        GridPane.setConstraints(directSlider, 1, rowNumber++);
        grid.getChildren().add(directSlider);
        directSlider.setShowTickMarks(true);
        directSlider.setSnapToTicks(true);
        directSlider.setMajorTickUnit(5);
        directSlider.setMinorTickCount(5);

        Label cssLabel = new Label("通过CSS配置的Slider(隐藏后刻度消失)");
        GridPane.setConstraints(cssLabel, 1, rowNumber++);
        grid.getChildren().add(cssLabel);

        Slider cssSlider = new Slider();
        GridPane.setConstraints(cssSlider, 1, rowNumber++);
        grid.getChildren().add(cssSlider);
        URL url = getClass().getResource("sample.css");
        String cssString = url.toExternalForm();
        scene.getStylesheets().add(cssString);
        cssSlider.getStyleClass().add("slider-style");

        Button button = new Button("隐藏窗口后重新显示");
        GridPane.setConstraints(button, 1, rowNumber++);
        grid.getChildren().add(button);
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                stage.hide();
                stage.show();
            }
        });

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

原因分析

这是JavaFX的一个已知bug,核心原因是:当Stage隐藏再显示时,Slider的皮肤(Skin)会被重新初始化。通过Java API直接设置的属性属于用户设置值,优先级高于CSS样式,不会被皮肤重置;而CSS中配置的-fx-show-tick-marks等属性属于样式值,在皮肤重建过程中没有被正确重新应用,导致刻度标记不再显示。

临时解决方案

方案一:手动触发CSS重新应用

监听Stage的显示状态,每次显示时手动触发Slider的CSS应用:

stage.showingProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue) {
        // 重新应用CSS样式
        cssSlider.applyCss();
        // 可选:重新添加样式类以强制刷新
        cssSlider.getStyleClass().remove("slider-style");
        cssSlider.getStyleClass().add("slider-style");
    }
});

方案二:混合配置

将-fx-show-tick-marks、-fx-snap-to-ticks这类关键属性通过Java API设置,其余样式(如颜色、布局)仍用CSS控制,避免皮肤重置时丢失配置:

cssSlider.setShowTickMarks(true);
cssSlider.setSnapToTicks(true);
cssSlider.setMajorTickUnit(5);
cssSlider.setMinorTickCount(5);
// 仅用CSS控制其他样式

内容的提问来源于stack exchange,提问作者dbueche

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 10:25:22