JavaFx 数字微调器 表格

使用JavaFx制作数字微调器。主要提供一种思路将代码继承到自己的项目中。

 

父类RootView完成初始化任务,初始化FXML,调用 initializeData(),initializeView()

import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

import java.math.BigDecimal;

public class NumberSpinnerView<T extends Number> extends RootView implements ChangeListener<String> {

    @FXML
    private TextField textFieldNumber;
    @FXML
    private Button buttonSubtraction;
    @FXML
    private Button buttonAdd;

    private Number minValue;
    private Number maxValue;
    // 标度值/精度/保留小数位
    private Integer scaleValue;
    // 分度值
    private Number scaleInterVal;

    public NumberSpinnerView() {
        this(null, null);
    }

    /**
     * @param minValue 最小值
     * @param maxValue 最大值
     */
    public NumberSpinnerView(Number minValue, Number maxValue) {
        this(minValue, maxValue, null);
    }

    /**
     * @param minValue 最小值
     * @param maxValue 最大值
     * @param scaleValue 标度值/精度/保留小数位
     */
    public NumberSpinnerView(Number minValue, Number maxValue, Integer scaleValue) {
        this(minValue, maxValue, scaleValue, null);
    }

    /**
     * @param minValue 最小值
     * @param maxValue 最大值
     * @param scaleValue 标度值/精度/保留小数位
     * @param scaleInterVal 分度值
     */
    public NumberSpinnerView(Number minValue, Number maxValue, Integer scaleValue, Number scaleInterVal) {
        this.setNumberSpinnerValue(minValue, maxValue, scaleValue, scaleInterVal);
    }


    // 根据标度计算分度值
    private Number getScaleInterValByScaleValue() {
        Number scaleInterVal = new Double(1);
        for (int i = 0; i < this.scaleValue; i++) {
            scaleInterVal = (double) scaleInterVal / 10;
        }
        return scaleInterVal;
    }

    // 按钮禁用绑定
    private void refreshButtonDisabled() {
        BigDecimal number = this.toBigDecimalFromString(this.getTextFieldNumber());
        int compareMax = number.compareTo(this.toBigDecimalFromString(this.maxValue.toString()));
        int compareMin = number.compareTo(this.toBigDecimalFromString(this.minValue.toString()));

        this.buttonAdd.setDisable(compareMax != -1);
        this.buttonSubtraction.setDisable(compareMin != 1);
    }

    @Override
    protected void initializeData() {
        this.minValue = 0;
        this.maxValue = Long.MAX_VALUE;
        this.scaleValue = BigDecimal.ROUND_UP;
        this.scaleInterVal = this.getScaleInterValByScaleValue();

        this.setTextFieldNumber(this.minValue);
    }

    @Override
    protected void initializeView() {
        this.getNumberProperty().addListener(this);
        this.setPrepareImage();
    }

    public void setPrepareImage() {
        Image imageButtonAdd = ResourceUtil.getImage("add", this.getClass().getClassLoader());
        if (imageButtonAdd == null) {
            Logger.error("Failed while getting add image");
        } else {
            this.buttonAdd.setGraphic(new ImageView(imageButtonAdd));
        }

        Image imageButtonSubtraction = ResourceUtil.getImage("sub", this.getClass().getClassLoader());
        if (imageButtonSubtraction == null) {
            Logger.error("Failed while getting sub image");
        } else {
            this.buttonSubtraction.setGraphic(new ImageView(imageButtonSubtraction));
        }
    }

    @FXML
    private void onClickAdd() {
        BigDecimal oldValue = this.toBigDecimalFromString(this.getTextFieldNumber());

        BigDecimal newValue = oldValue.add(new BigDecimal(this.scaleInterVal.toString()));
        newValue = newValue.min(new BigDecimal(this.maxValue.toString()));

        this.setTextFieldNumber(newValue);
    }

    @FXML
    private void onClickSubtraction() {
        BigDecimal oldValue = this.toBigDecimalFromString(this.getTextFieldNumber());

        BigDecimal newValue = oldValue.subtract(new BigDecimal(this.scaleInterVal.toString()));
        newValue = newValue.max(new BigDecimal(this.minValue.toString()));

        this.setTextFieldNumber(newValue);
    }

    public void setTextFieldNumberEditable(boolean editable) {
        this.textFieldNumber.setEditable(editable);
    }

    public void setNumberSpinnerValue(Number minValue, Number maxValue, Integer scaleValue, Number scaleInterVal) {
        if (minValue != null) {
            this.minValue = minValue;
        }

        if (maxValue != null) {
            this.maxValue = maxValue;
        }

        if (scaleValue != null) {
            this.scaleValue = scaleValue;
        }

        this.scaleInterVal = this.getScaleInterValByScaleValue();
        if (scaleInterVal != null) {
            this.scaleInterVal = scaleInterVal;
        }

        this.setTextFieldNumber(this.minValue);
    }

    public String getTextFieldNumber() {
        return this.textFieldNumber.getText();
    }

    public BigDecimal toBigDecimalFromString(String value) {
        BigDecimal decimal = new BigDecimal(value);
        return decimal.setScale(this.scaleValue, BigDecimal.ROUND_DOWN);
    }

    public void setTextFieldNumber(Number value) {
        this.textFieldNumber.setText(value.toString());
    }

    public StringProperty getNumberProperty() {
        return this.textFieldNumber.textProperty();
    }

    public void selectAllText() {
        this.textFieldNumber.selectAll();
    }

    public void requestFocusText() {
        this.textFieldNumber.requestFocus();
    }

    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        NumberSpinnerView<T> self = NumberSpinnerView.this;
        try {
            BigDecimal value = self.toBigDecimalFromString(newValue);
            value = value.min(new BigDecimal(self.maxValue.toString()));
            value= value.max(new BigDecimal(self.minValue.toString()));

            String num = (value + ".") == newValue ? newValue : value.toString();
            self.textFieldNumber.setText(num);
        } catch (Exception e) {
            self.textFieldNumber.setText(oldValue);
        }
        self.refreshButtonDisabled();
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.*?>
<fx:root maxWidth="1.7976931348623157E308" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <HBox maxWidth="1.7976931348623157E308" VBox.vgrow="ALWAYS">
            <children>
                <TextField fx:id="textFieldNumber" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS">
                    <HBox.margin>
                        <Insets />
                    </HBox.margin>
                </TextField>
                <Button fx:id="buttonSubtraction" disable="true" mnemonicParsing="false" onAction="#onClickSubtraction" />
                <Button fx:id="buttonAdd" mnemonicParsing="false" onAction="#onClickAdd" />
            </children>
        </HBox>
    </children>
</fx:root>

 

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.EventHandler;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.util.Callback;
import javafx.util.StringConverter;
import javafx.util.converter.IntegerStringConverter;

public class NumberSpinnerCell<S, T extends Number> extends TableCell<S, T> {
    private ObjectProperty<StringConverter<T>> converter;

    public static <S, T extends Number> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn() {
        return forTableColumn((StringConverter) new IntegerStringConverter());
    }

    public static <S, T extends Number> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn(StringConverter<T> var0) {
        return forTableColumn(var0, null, null);
    }

    public static <S, T extends Number> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn(
            StringConverter<T> var0, Number minValue, Number maxValue) {
        return forTableColumn(var0, minValue, maxValue, null, null);
    }

    /**
     * @param var0 类型转换器
     * @param minValue 最小值
     * @param maxValue 最大值
     * @param scaleValue 标度值/精度/保留小数位
     * @param scaleInterVal 分度值
     * @param <S>
     * @return
     */
    public static <S, T extends Number> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn(
            StringConverter<T> var0, final Number minValue, final Number maxValue, final Integer scaleValue, final Number scaleInterVal) {

        return new Callback<TableColumn<S, T>, TableCell<S, T>>() {
            @Override
            public TableCell<S, T> call(TableColumn<S, T> param) {
                return new NumberSpinnerCell<S, T>(var0, minValue, maxValue, scaleValue, scaleInterVal);
            }
        };
    }


    private NumberSpinnerView numberSpinnerView;

    public NumberSpinnerCell() {
        this((StringConverter<T>) new IntegerStringConverter(), null, null);
    }

    public NumberSpinnerCell(StringConverter<T> var1, Number minValue, Number maxValue) {

        this(var1, minValue, maxValue, null, null);
    }

    public NumberSpinnerCell(StringConverter<T> var1, Number minValue, Number maxValue, Integer scaleValue, Number scaleInterVal) {
        this.converter = new SimpleObjectProperty<>(this, "converter");
        this.setConverter(var1);

        this.numberSpinnerView = new NumberSpinnerView(minValue, maxValue, scaleValue, scaleInterVal);
        setGraphic(null);

        this.setOnKeyReleased(new EventHandler<KeyEvent>() {
            public void handle(KeyEvent event) {
                NumberSpinnerCell<S, T> self = NumberSpinnerCell.this;
                if (event.getCode() == KeyCode.ENTER) {
                    String number = self.getNumberSpinnerView().getTextFieldNumber();
                    self.commitEdit(self.getConverter().fromString(number));
                } else if (event.getCode() == KeyCode.ESCAPE) {
                    self.cancelEdit();
                }

                event.consume();
            }
        });
    }

    public final ObjectProperty<StringConverter<T>> converterProperty() {
        return this.converter;
    }

    public final void setConverter(StringConverter<T> var1) {
        this.converterProperty().set(var1);
    }

    public final StringConverter<T> getConverter() {
        return (StringConverter<T>) this.converterProperty().get();
    }

    @Override
    public void startEdit() {
        if (!this.isEditable() || !getTableView().isEditable() || !getTableColumn().isEditable()) {
            return;
        }

        super.startEdit();

        if (isEditing()) {
            this.setText(null);
            this.setGraphic(this.getNumberSpinnerView());
            this.getNumberSpinnerView().setTextFieldNumber(this.getItem());
            this.getNumberSpinnerView().selectAllText();
            this.getNumberSpinnerView().requestFocusText();
        }
    }

    public void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            this.setText(null);
            this.setGraphic(null);
        } else {

            this.setText(this.myText());
        }
    }

    private String myText() {
        if (this.getItem() != null) {
            return this.getItem().toString();
        } else {
            return "";
        }
    }

    @Override
    public void commitEdit(T newValue) {
        super.commitEdit(newValue);

        this.setItem(newValue);
        this.setGraphic(null);
        this.setText(this.myText());
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();

        this.setGraphic(null);
        this.setText(this.myText());
    }

    public NumberSpinnerView getNumberSpinnerView() {
        return this.numberSpinnerView;
    }
}

通过调用接口 

this.columnID.setCellValueFactory(new PropertyValueFactory<PermissionFilter, Double>("columnID"));
this.columnID.setCellFactory(NumberSpinnerCell.<PermissionFilter, Double>forTableColumn(new DoubleStringConverter(), -1, 1, BigDecimal.ROUND_DOWN, null));
 public static <S, T extends Number> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn(
            StringConverter<T> var0, final Number minValue, final Number maxValue, final Integer scaleValue, final Number scaleInterVal) 

var0 :为继承StringConverter<T> 的类型转换器,默认为IntegerStringConverter

minValue:设置数字微调器的最小值, 默认为0

maxValue:设置数字微调器的最大值,默认为 Long.MAX_VALUE

scaleValue:设置数字微调器的标度值/保留几个小数位,默认值为 (BigDecimal.ROUND_UP)0

scaleInterVal:设置数字微调器的分度值,默认根据scaleValue标度值计算的一个单位

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值