如何单独引用 RangeSlider 的每个拇指 (ControlsFX)

Posted

技术标签:

【中文标题】如何单独引用 RangeSlider 的每个拇指 (ControlsFX)【英文标题】:How to Individually Reference Each Thumb of a RangeSlider (ControlsFX) 【发布时间】:2017-05-20 17:54:01 【问题描述】:

我正在尝试绑定要显示在RangeSlider 上下拇指上方的标签。

无论用户将其滑动到何处,标签的位置都应始终保持在其各自拇指上方。像这样:

我的方法是将侦听器附加到每个拇指,以便我可以将标签设置为每次用户滑动时都有适当的 X/Y 坐标。但是当我运行以下代码时,我似乎无法通过 css 选择器获得对个人拇指的引用。

我关注了this post,但这只用了一个拇指,因此很容易参考。您如何在我的上下文中正确使用 CSS 选择器,或者如果我的有缺陷,有什么更好的方法?

控制器

public class SliderDemoController implements Initializable 
    @FXML
    private RangeSlider range;
    @Override
    public void initialize(URL location, ResourceBundle resources) 
        Pane thumb = (Pane) range.lookup(".range-slider .low-thumb");
        System.out.println(thumb); // <-- Prints null
    

主要

public class SliderDemoMain extends Application 
    public static void main(String[] args) 
        launch(args);
    

    @Override
    public void start(Stage initStage) throws IOException 
        FXMLLoader loader = new FXMLLoader(Drag.class.getClassLoader().getResource("sliderdemo.fxml"));
        Parent root = loader.load();
        Scene scene = new Scene(root);
        Stage primaryStage = new Stage();
        primaryStage.setTitle("Slider Demo");
        primaryStage.setScene(scene);
        primaryStage.show();
    

styleMain.css

.range-slider .range-bar 
    -fx-background-color: grey;


.range-slider .low-thumb 
     //....

.range-slider .high-thumb 
    //....

sliderdemo.fxml 的顶行

<HBox fx:id="menuBar" maxHeight="-Infinity" minHeight="-Infinity" prefHeight="79.0" stylesheets="@styleMain.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.propertydrop.SliderDemoController">

【问题讨论】:

【参考方案1】:

要使 CSS 查找正常工作,您需要应用 CSS、制作布局通道以及成为场景一部分的节点。 (请注意您引用的帖子中的这一点,答案中的代码在执行查找之前会仔细执行这些步骤。)

这在控制器中很难实现,因为initialize() 方法通常在将 FXML 中的根节点添加到场景之前调用。您可以通过观察节点的sceneProperty() 来破解它,并在它设置为非空值时做出响应。 (是的,这有点骇人听闻……):

public class SliderDemoController implements Initializable 
    @FXML
    private RangeSlider range;
    @Override
    public void initialize(URL location, ResourceBundle resources) 
        ChangeListener<Scene> initializer = new ChangeListener<Scene>() 
            @Override
            public void changed(ObservableValue<? extends Scene> obs, Scene oldScene, Scene newScene)  
                if (newScene != null) 
                    range.applyCss();
                    range.getParent().layout();
                    Pane thumb = (Pane) range.lookup(".range-slider .low-thumb");
                    System.out.println(thumb); // <-- No longer null
                    range.sceneProperty().removeListener(this);
                
            
        ;
        range.sceneProperty().addListener(initializer);
    

根据您的具体要求,您也许可以避免一些不那么难看的事情,例如在事件处理程序或滑块的 highValuelowValue 属性上的侦听器中执行查找。

【讨论】:

就个人而言,我不认为这是一种黑客行为。我只能说这是必要的,因为 API 没有提供开箱即用的“快捷方式”。很高兴甚至有解决方案:) @Jai 这是一个 hack :)。做你想做的事情的“API-正确”方法是为 RangeSlider 创建一个新皮肤,其中包括你想要显示的标签。然而,由于(目前)皮肤类不公开,这将涉及重新发明***并且需要大量工作。 @James_D,只要这个 hack 在商业环境中是可靠的,我就可以接受美学。你已经回答了我的问题,谢谢。在range.lowValueProperty().addListener 中执行查找确实足够了。 +1

以上是关于如何单独引用 RangeSlider 的每个拇指 (ControlsFX)的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 范围滑块

iPhone 范围滑块

Flutter - 范围滑块

如何在 Flutter 中制作这个自定义 RangeSlider?

plotly rangeslider 如何确定是不是选择了范围

如何防止在Ion.RangeSlider中单击间隔?