[英]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 时,每个鼠标移动的值都会发生变化。 所以比较来自监听器的
oldValue
和newValue
是行不通的。 你需要另一种策略。
您可以在初始化时保存默认值,并在释放鼠标时将当前值与默认值进行比较:
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.