繁体   English   中英

JavaFX - 将 Slider 绑定到按钮的禁用属性

[英]JavaFX - Binding Slider to Button's Disable Property

仅当滑块的拇指超过新值(或位置)时,我才尝试启用按钮。

下面是 window 及其初始情况:

在此处输入图像描述

一旦我开始拖动 Thumb,按钮就会被激活,即使 Thumb 也没有超过新值(即使在值之间也被激活):

在此处输入图像描述

如果我中止拖动操作(释放鼠标按钮)并且拇指返回到初始 position(或值),则按钮不会禁用。

在此处输入图像描述

编码:

private void configSldFontSize() {
    
    sldFontSize.valueProperty().addListener((ov, oldValue, newValue) -> {

        if (oldValue == newValue) {
            btnApply.setDisable(true);
        } else {
            btnApply.setDisable(false);
        }

    });

}

可能是配置错误?

private void setUpSlrFontSize() {

    sldFontSize.setMin(0);
    sldFontSize.setMax(FontSize.values().length - 1);
    sldFontSize.setValue(viewFactory.getFontSize().ordinal());
    sldFontSize.setMajorTickUnit(1);
    sldFontSize.setMinorTickCount(0);
    sldFontSize.setBlockIncrement(1);
    sldFontSize.setSnapToTicks(true);
    sldFontSize.setShowTickMarks(true);
    sldFontSize.setShowTickLabels(true);
    sldFontSize.setLabelFormatter(new StringConverter<Double>() {

        @Override
        public Double fromString(String arg0) {
            return null;
        }

        @Override
        public String toString(Double obj) {
            int i = obj.intValue();
            return FontSize.values()[i].toString();
        }

    });

}

======= 复制条件的小代码实现 ==========

注意力:

我正在使用 Java 11 (我想 Java 8 没有必要)。 因此,可能需要在“运行配置”中包含以下行。

在此处输入图像描述

In Package Explorer: right mouse button on "Main.Java => Run As => Run Configurations...", select "(x) = Arguments" tab and put the line as image below, CHANGING THE PATH TO YOUR JAVAFX LIB FOLDER .

在此处输入图像描述

代码Main.java

public class Main extends Application {
@Override
public void start(Stage primaryStage) {
    try {
        VBox root = new VBox();
        
        Button btnApply = new Button("Apply");
        btnApply.setDisable(true);
        
        Slider sldFontSize = new Slider();
        sldFontSize.setMin(0);
        sldFontSize.setMax(2);
        sldFontSize.setValue(1);
        sldFontSize.setMajorTickUnit(1);
        sldFontSize.setMinorTickCount(0);
        sldFontSize.setBlockIncrement(1);
        sldFontSize.setSnapToTicks(true);
        sldFontSize.setShowTickMarks(true);
        sldFontSize.setShowTickLabels(true);
        
        sldFontSize.valueProperty().addListener((ov, oldValue, newValue) -> {

            if (oldValue == newValue) {
                btnApply.setDisable(true);
            } else {
                btnApply.setDisable(false);
            }

        });
        
        root.getChildren().addAll(sldFontSize, btnApply);
        
        Scene scene = new Scene(root,200,100);
        scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

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

}

通常,您可以从 slider 创建一个表示您想要的实际值的单独属性,然后使用该属性注册一个侦听器。 请注意,仅当值实际更改时才会通知更改侦听器,因此侦听器中的if (oldValue==newValue)将始终为 false。

在这种情况下,由于感兴趣的值只是将滑块的值转换为int的结果,因此您只需将IntegerProperty绑定到 slider 值:

        IntegerProperty intValue = new SimpleIntegerProperty();
        intValue.bind(sldFontSize.valueProperty());

        intValue.addListener((ov, oldValue, newValue) -> btnApply.setDisable(false));

更一般地,创建自定义绑定或使用sldFontSize.valueProperty()注册一个侦听器,以更新您的其他属性。 例如使用你的FontSize ,我认为这是一个enum

ObjectProperty<FontSize> fontSizeProperty = new SimpleObjectProperty<>();
fontSizeProperty.bind(Bindings.createObjectBinding(
    () -> FontSize.value()[(int) sldFontSize.getValue()],
    sldFontSize.valueProperty()));
fontSizeProperty.addListener((obs, oldFontSize, newFontSize) -> btnApply.setDisable(false));

为了更精确,您可以实现舍入而不是简单的强制转换等。您可能还想保存“最后应用的值”并在决定是否禁用/启用按钮等时与之进行比较。

把所有这些放在一起,你会得到类似的东西:

public class Main extends Application {
    
    @Override
    public void start(Stage primaryStage) {
        try {
            VBox root = new VBox();
            
            IntegerProperty lastSavedFontSize = new SimpleIntegerProperty(1);
            IntegerProperty sldIntValue = new SimpleIntegerProperty();

            Button btnApply = new Button("Apply");
            btnApply.setOnAction(e -> lastSavedFontSize.set(sldIntValue.get()));
            btnApply.disableProperty().bind(sldIntValue.isEqualTo(lastSavedFontSize));

            Slider sldFontSize = new Slider();
            sldFontSize.setMin(0);
            sldFontSize.setMax(2);
            sldFontSize.setValue(lastSavedFontSize.get());
            sldFontSize.setMajorTickUnit(1);
            sldFontSize.setMinorTickCount(0);
            sldFontSize.setBlockIncrement(1);
            sldFontSize.setSnapToTicks(true);
            sldFontSize.setShowTickMarks(true);
            sldFontSize.setShowTickLabels(true);
            
            sldIntValue.bind(Bindings.createIntegerBinding(
                    () ->(int) Math.round(sldFontSize.getValue()), 
                    sldFontSize.valueProperty()));


            root.getChildren().addAll(sldFontSize, btnApply);

            Scene scene = new Scene(root, 200, 100);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

另一种方法完全是利用滑块的valueChangingProperty() 当且仅当用户当前正在更改值时,此 boolean 属性才为真。 请注意,在某些情况下, valueChangingProperty()可能会在 slider 的最终值设置之前变为 false,因此最安全的做法是同时监听这两个属性。 这是使用这种方法的版本:

public class Main extends Application {
    
    @Override
    public void start(Stage primaryStage) {
        try {
            VBox root = new VBox();
            
            IntegerProperty lastSavedFontSize = new SimpleIntegerProperty(1);

            Button btnApply = new Button("Apply");
            btnApply.setDisable(true);  


            Slider sldFontSize = new Slider();
            sldFontSize.setMin(0);
            sldFontSize.setMax(2);
            sldFontSize.setValue(lastSavedFontSize.get());
            sldFontSize.setMajorTickUnit(1);
            sldFontSize.setMinorTickCount(0);
            sldFontSize.setBlockIncrement(1);
            sldFontSize.setSnapToTicks(true);
            sldFontSize.setShowTickMarks(true);
            sldFontSize.setShowTickLabels(true);

            btnApply.setOnAction(e -> {
                // apply change, and do
                lastSavedFontSize.set((int) sldFontSize.getValue());
            });
            
            ChangeListener<Object> sliderListener = (obs, oldV, newV) -> {
                if (!sldFontSize.isValueChanging()) {
                    btnApply.setDisable((int)sldFontSize.getValue() == lastSavedFontSize.get());
                }
            };

            sldFontSize.valueProperty().addListener(sliderListener);
            sldFontSize.valueChangingProperty().addListener(sliderListener);
            lastSavedFontSize.addListener(sliderListener);

            root.getChildren().addAll(sldFontSize, btnApply);

            Scene scene = new Scene(root, 200, 100);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

当您移动 slider 时,每个鼠标移动的值都会发生变化。 在此处输入图像描述 所以比较来自监听器的oldValuenewValue是行不通的。 你需要另一种策略。

您可以在初始化时保存默认值,并在释放鼠标时将当前值与默认值进行比较:

sldFontSize.setOnMouseReleased(event -> btnApply.setDisable(sldFontSize.getValue() == defaultValue));

完整代码:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Sample extends Application {

    @Override
    public void start(Stage primaryStage) {
        try {
            VBox root = new VBox();

            Button btnApply = new Button("Apply");
            btnApply.setDisable(true);

            Slider sldFontSize = new Slider();
            sldFontSize.setMin(0);
            sldFontSize.setMax(2);
            sldFontSize.setValue(1);
            sldFontSize.setMajorTickUnit(1);
            sldFontSize.setMinorTickCount(0);
            sldFontSize.setBlockIncrement(1);
            sldFontSize.setSnapToTicks(true);
            sldFontSize.setShowTickMarks(true);
            sldFontSize.setShowTickLabels(true);

            double defaultValue = sldFontSize.getValue();
            sldFontSize.setOnMouseReleased(event -> btnApply.setDisable(sldFontSize.getValue() == defaultValue));

            root.getChildren().addAll(sldFontSize, btnApply);
            Scene scene = new Scene(root, 200, 100);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM