好的,这是我的情况。当编辑器为空时,我需要禁用两个微调器按钮,这是我需要完成的最后一个部分" custom"零件。继承我的SSCCE。
当焦点丢失时:默认值设置为零,文本会更新。
它只接受带小数点后2位的十进制值,它只接受货币或百分比值。
无需添加任何其他内容。
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class test extends Application{
@Override
public void start(Stage primaryStage) throws Exception {
VBox v = new VBox();
v.setPadding(new Insets(20));
Spinner<Double> spinner = new Spinner<>();
spinner.setEditable(true);
Button dummy = new Button("dummy focus");
v.getChildren().addAll(spinner,dummy);
//----------------------------------HERE IS EVERYTHING RELATED TO THE SPINNER---------------------------------------------
spinner.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0, 100));
spinner.getValueFactory().setValue(0.0);
spinner.getEditor().textProperty().addListener((obs,old,gnu)->{
if(gnu.isEmpty()) {
System.out.println("empty, buttons should be disabled here, they will be disabled after this ");
spinner.getValueFactory().setValue(0.0);
return;
}
System.out.println("enabling buttons");
if(!gnu.matches("^\\d*\\.?\\d*$")) {
try {
spinner.getEditor().setText(old);
spinner.getValueFactory().setValue(Double.parseDouble(old));
}catch (NumberFormatException e) {
System.out.println("invalid string, previous value was empty, no biggie you are safe: Current value : "+spinner.getValueFactory().getValue());
}
} else {
if((Double.parseDouble(gnu)*100)%1!=0) {
spinner.getEditor().setText(old);
spinner.getValueFactory().setValue(Double.parseDouble(old));
}
/*
* You can use this to validate inside a range, for example. PERCENTAGES : 0 ~ 100
*
double val = Double.parseDouble(gnu)*100;
if(val%1!=0 || val>10000 || val<0) {
spinner.getEditor().setText(old);
spinner.getValueFactory().setValue(Double.parseDouble(old));
}
*/
}
});
spinner.getEditor().setOnKeyPressed(e->{
switch (e.getCode()) {
case UP:
spinner.increment(1);
break;
case DOWN:
spinner.decrement(1);
break;
default:
break;
}
});
spinner.setOnScroll(e->{
if(e.getDeltaY()>0)
spinner.increment(1);
else
spinner.decrement(1);
});
spinner.getEditor().focusedProperty().addListener((obs,old,niu)->{
if(!niu && spinner.getEditor().getText().isEmpty()) {
spinner.getEditor().setText("0");
spinner.getValueFactory().setValue(0.0);
}
});
//-----------------------------------------------------------------------------------------------------------------------------------------
Scene sc = new Scene(v);
primaryStage.setScene(sc);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
编辑:
也会发生按键和滚动事件。
答案 0 :(得分:1)
我担心你不能只禁用微调器的按钮。但是在Editor
(实际上是TextField
)之后设置值是空的呢?通过使用这样的解决方案,您可以在单击按钮后获得任何异常 - 值仅从0
递增。我稍微修改了您的gnu.isEmpty()
代码。
if(gnu.isEmpty()) {
System.out.println("empty, buttons should be disabled here, they will be disabled after this ");
double valueToSet = 0.0;
spinner.getValueFactory().setValue(valueToSet);
Platform.runLater(() -> spinner.getEditor().setText(Double.toString(valueToSet)));
return;
}
另一件事是,你的代码允许放置&#39; 0&#39;作为第一个数字,即使之后有另一个数字。检查代码,应该解决问题(将其与以if(!gnu.matches("^\\d*\\.?\\d*$"))
开头的整个if / else语句交换):
if (!isDouble(gnu)) {
gnu = old;
}
spinner.getEditor().setText(gnu);
isDouble
是一种方法:
private boolean isDouble(String string) {
boolean startsWithZero =
string.startsWith("0") &&
(string.length() > 1) &&
(!string.startsWith("0."));
boolean minusZeroCondition =
string.startsWith("-0") &&
(string.length() > 2) &&
(!string.startsWith("-0."));
boolean containsTypeSpecificLetters =
Pattern.matches(".*[a-zA-Z].*", string);
boolean isEmpty = string.equals("");
boolean isMinus = string.equals("-");
try {
Double.parseDouble(string);
return !(startsWithZero || minusZeroCondition || containsTypeSpecificLetters);
} catch (IllegalArgumentException exception) {
return isEmpty || isMinus;
}
}
答案 1 :(得分:1)
我也在寻找一种方法来仅禁用按钮。我需要在仍然允许复制/粘贴的同时禁用更改Spinner
的值,所以我在源代码中做了一些挖掘。
我发现的是,虽然按钮实际上并不是Spinner
对象本身的一部分,但它们却是Spinner
的{{1}}的一部分(它们也不是SpinnerSkin
s,但Button
s),因此我设法仅禁用了以下按钮(在Kotlin中):
StackPane
我必须听属性更改,因为skinProperty并非在初始化时设置,而是仅在处理CSS之后设置。如果您完全确定您的微调框已经显示并且设置了外观,则可以直接致电val editing = SimpleBooleanProperty(false)
val spinner = Spinner<Int>()
spinner.skinProperty().addListener { observable, oldValue, newValue ->
// only bind if the skin is an instance of `SpinnerSkin`
if (newValue != null && newValue is SpinnerSkin<*>) {
(skin as SpinnerSkin<*>).children
// only select the children that are `StackPane`s (the buttons)
.filter { it is StackPane }
// bind the `disableProperty` of the buttons to our property for whether we're editing
.forEach { disableProperty().bind(editing.not()) }
}
}
。