JavaFX Spinner禁用空编辑器上的按钮

时间:2017-08-10 02:06:37

标签: javafx spinner

好的,这是我的情况。当编辑器为空时,我需要禁用两个微调器按钮,这是我需要完成的最后一个部分" 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);
    }

}

编辑

也会发生按键和滚动事件。

2 个答案:

答案 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()) } } }