javafx日期控件

package com.taocares.naoms.client.model.common.custom.control;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;

import javafx.beans.NamedArg;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.SpinnerValueFactory;
import javafx.util.StringConverter;

public class LocalDateTimeSpinnerValueFactory extends SpinnerValueFactory{
/**
* Creates a new instance of the LocalDateSpinnerValueFactory, using the
* value returned by calling {@code LocalDate#now()} as the initial value,
* and using a stepping amount of one day.
*/
public LocalDateTimeSpinnerValueFactory() {
this(LocalDateTime.now());

}

/**
 * Creates a new instance of the LocalDateSpinnerValueFactory, using the
 * provided initial value, and a stepping amount of one day.
 *
 * @param initialValue The value of the Spinner when first instantiated.
 */
public LocalDateTimeSpinnerValueFactory(@NamedArg("initialValue") LocalDateTime initialValue) {
    this(LocalDateTime.MIN, LocalDateTime.MAX, initialValue);
}

/**
 * Creates a new instance of the LocalDateSpinnerValueFactory, using the
 * provided initial value, and a stepping amount of one day.
 *
 * @param min The minimum allowed double value for the Spinner.
 * @param max The maximum allowed double value for the Spinner.
 * @param initialValue The value of the Spinner when first instantiated.
 */
public LocalDateTimeSpinnerValueFactory(@NamedArg("min") LocalDateTime min,
                                    @NamedArg("min") LocalDateTime max,
                                    @NamedArg("initialValue") LocalDateTime initialValue) {
    this(min, max, initialValue, 1, ChronoUnit.DAYS,"yyyy-MM-dd HH:mm:ss");
}

/**
 * Creates a new instance of the LocalDateSpinnerValueFactory, using the
 * provided min, max, and initial values, as well as the amount to step
 * by and {@link java.time.temporal.TemporalUnit}.
 *
 * 

To better understand, here are a few examples: * *

    *
  • To step by one day from today: {@code new LocalDateSpinnerValueFactory(LocalDate.MIN, LocalDate.MAX, LocalDate.now(), 1, ChronoUnit.DAYS)}
  • *
  • To step by one month from today: {@code new LocalDateSpinnerValueFactory(LocalDate.MIN, LocalDate.MAX, LocalDate.now(), 1, ChronoUnit.MONTHS)}
  • *
  • To step by one year from today: {@code new LocalDateSpinnerValueFactory(LocalDate.MIN, LocalDate.MAX, LocalDate.now(), 1, ChronoUnit.YEARS)}
  • *
* * @param min The minimum allowed double value for the Spinner. * @param max The maximum allowed double value for the Spinner. * @param initialValue The value of the Spinner when first instantiated. * @param amountToStepBy The amount to increment or decrement by, per step. * @param temporalUnit The size of each step (e.g. day, week, month, year, etc) */ public LocalDateTimeSpinnerValueFactory(@NamedArg("min") LocalDateTime min, @NamedArg("min") LocalDateTime max, @NamedArg("initialValue") LocalDateTime initialValue, @NamedArg("amountToStepBy") long amountToStepBy, @NamedArg("temporalUnit") TemporalUnit temporalUnit, @NamedArg("pattern") String pattern) { setMin(min); setMax(max); setAmountToStepBy(amountToStepBy); setTemporalUnit(temporalUnit); setPattern(pattern); setConverter(new StringConverter() { @Override public String toString(LocalDateTime object) { if (object == null) { return ""; } DateTimeFormatter stf = DateTimeFormatter.ofPattern(getPattern()); return object.format(stf); } @Override public LocalDateTime fromString(String string) { return LocalDateTime.parse(string); } }); valueProperty().addListener((o, oldValue, newValue) -> { // when the value is set, we need to react to ensure it is a // valid value (and if not, blow up appropriately) if(newValue!=null){ if (getMin() != null && newValue.isBefore(getMin())) { setValue(getMin()); } else if (getMax() != null && newValue.isAfter(getMax())) { setValue(getMax()); } } }); setValue(initialValue != null ? initialValue : LocalDateTime.now()); } /*********************************************************************** * * * Properties * * * **********************************************************************/ // --- min private ObjectProperty min = new SimpleObjectProperty(this, "min") { @Override protected void invalidated() { LocalDateTime currentValue = LocalDateTimeSpinnerValueFactory.this.getValue(); if (currentValue == null) { return; } final LocalDateTime newMin = get(); if (newMin.isAfter(getMax())) { setMin(getMax()); return; } if (currentValue.isBefore(newMin)) { LocalDateTimeSpinnerValueFactory.this.setValue(newMin); } } }; public final void setMin(LocalDateTime value) { min.set(value); } public final LocalDateTime getMin() { return min.get(); } /** * Sets the minimum allowable value for this value factory */ public final ObjectProperty minProperty() { return min; } // --- max private ObjectProperty max = new SimpleObjectProperty(this, "max") { @Override protected void invalidated() { LocalDateTime currentValue = LocalDateTimeSpinnerValueFactory.this.getValue(); if (currentValue == null) { return; } final LocalDateTime newMax = get(); if (newMax.isBefore(getMin())) { setMax(getMin()); return; } if (currentValue.isAfter(newMax)) { LocalDateTimeSpinnerValueFactory.this.setValue(newMax); } } }; public final void setMax(LocalDateTime value) { max.set(value); } public final LocalDateTime getMax() { return max.get(); } /** * Sets the maximum allowable value for this value factory */ public final ObjectProperty maxProperty() { return max; } // --- temporalUnit private ObjectProperty temporalUnit = new SimpleObjectProperty<>(this, "temporalUnit"); public final void setTemporalUnit(TemporalUnit value) { temporalUnit.set(value); } public final TemporalUnit getTemporalUnit() { return temporalUnit.get(); } /** * The size of each step (e.g. day, week, month, year, etc). */ public final ObjectProperty temporalUnitProperty() { return temporalUnit; } // --- amountToStepBy private LongProperty amountToStepBy = new SimpleLongProperty(this, "amountToStepBy"); public final void setAmountToStepBy(long value) { amountToStepBy.set(value); } public final long getAmountToStepBy() { return amountToStepBy.get(); } /** * Sets the amount to increment or decrement by, per step. */ public final LongProperty amountToStepByProperty() { return amountToStepBy; } //---- pattern private StringProperty pattern=new SimpleStringProperty(this, "pattern"); public final void setPattern(String value){ pattern.setValue(value); } public final String getPattern(){ return pattern.get(); } public final StringProperty patternProperty(){ return pattern; } /*********************************************************************** * * * Overridden methods * * * **********************************************************************/ /** {@inheritDoc} */ @Override public void decrement(int steps) { final LocalDateTime currentValue = getValue(); final LocalDateTime min = getMin(); if(currentValue==null){ setValue(LocalDateTime.now()); return; } LocalDateTime newValue = currentValue.minus(getAmountToStepBy() * steps, getTemporalUnit()); if (min != null && isWrapAround() && newValue.isBefore(min)) { // we need to wrap around newValue = getMax(); } setValue(newValue); } /** {@inheritDoc} */ @Override public void increment(int steps) { final LocalDateTime currentValue = getValue(); final LocalDateTime max = getMax(); if(currentValue==null){ setValue(LocalDateTime.now()); return; } LocalDateTime newValue = currentValue.plus(getAmountToStepBy() * steps, getTemporalUnit()); if (max != null && isWrapAround() && newValue.isAfter(max)) { // we need to wrap around newValue = getMin(); } setValue(newValue); }

}

package com.taocares.naoms.client.model.common.custom.control;

import java.time.temporal.ChronoUnit;

/**
* 时间控件 ENUM
*
* @author wxx
*
*/
public enum LocalDateTimeSpinnerCode {
YEARS(0, 4, 1, ChronoUnit.YEARS),
MONTHS(5, 7, 2, ChronoUnit.MONTHS),
DAYS(8, 10, 3, ChronoUnit.DAYS),
HOURS(11, 13, 4, ChronoUnit.HOURS),
MINUTES(14, 16, 5, ChronoUnit.MINUTES),
SECONDS(17, 19, 6, ChronoUnit.SECONDS);

private Integer start;
private Integer end;
private Integer index;
private ChronoUnit chronoUnit;

LocalDateTimeSpinnerCode(Integer start, Integer end, Integer index, ChronoUnit chronoUnit) {
    this.start = start;
    this.end = end;
    this.index = index;
    this.chronoUnit = chronoUnit;
}

/**
 * 根据Start获取对象
 *
 * @param start
 * @return
 */
public static LocalDateTimeSpinnerCode getCodeByStart(Integer start) {
    for (LocalDateTimeSpinnerCode code : LocalDateTimeSpinnerCode.values()) {
        if (code.getStart() <= start && code.getEnd() >= start) {
            return code;
        }
    }
    return null;
}
/**
 * 根据Index 获取对象
 * @param index
 * @return
 */
public static LocalDateTimeSpinnerCode getCodeByIndex(Integer index){
    for (LocalDateTimeSpinnerCode code : LocalDateTimeSpinnerCode.values()) {
        if (code.getIndex()==index) {
            return code;
        }
    }
    return null;
}

public Integer getStart() {
    return start;
}

public Integer getEnd() {
    return end;
}

public Integer getIndex() {
    return index;
}

public ChronoUnit getChronoUnit() {
    return chronoUnit;
}

}
package com.taocares.naoms.client.model.common.custom.control;

import java.time.LocalDateTime;
import java.util.Date;

import com.taocares.naoms.client.model.common.util.LocalDateConvert;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.control.IndexRange;
import javafx.scene.control.Spinner;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;

/**
* 时间控件 目前适用于yyyy-MM-dd HH:mm 格式 使用方式: new LocalDateTimeSpinner()||new
* LocalDateTimeSpinner(Date date) 存取值方式: setDate(Date date),Date
* getDate()||LocalDateTime getValue()
*
* @author wxx
* @author stone 添加监听,左右切换以及键入验证
*
*/
public class LocalDateTimeSpinner extends Spinner {
private static Integer CURRENT_INDEX = -1;
private static Integer CURRENT = 0;
private boolean isMinute = false;
LocalDateTimeSpinnerValueFactory ldtsvf = new LocalDateTimeSpinnerValueFactory();

public LocalDateTimeSpinner() {
    init();
}

public LocalDateTimeSpinner(Date date) {
    init();
    setDate(date);
}

public void setDate(Date date) {
    if (date != null) {
        this.getValueFactory().setValue(LocalDateConvert.UDateToLocalDateTime(date));
    } else {
        this.getValueFactory().setValue(null);
    }
}

public Date getDate() {
    if (this.getValueFactory().getValue() != null) {
        return LocalDateConvert.LocalDateTimeToUdate(this.getValueFactory().getValue());
    }
    return null;
}

/**
 * 切换调整元素
 */
private void switchTemporalUnit() {
    TextField tf = this.getEditor();
    LocalDateTimeSpinnerCode code = LocalDateTimeSpinnerCode.getCodeByIndex(CURRENT_INDEX);
    if (code == null) {
        IndexRange range = tf.getSelection();
        code = LocalDateTimeSpinnerCode.getCodeByStart(range.getStart());
    }
    tf.selectRange(code.getStart(), code.getEnd());
    CURRENT_INDEX = code.getIndex();
    ldtsvf.setTemporalUnit(code.getChronoUnit());
}

/**
 * 双击
 */
private void switchTemporalUnitByDoubleClick() {
    TextField tf = this.getEditor();
    IndexRange range = tf.getSelection();
    LocalDateTimeSpinnerCode code = LocalDateTimeSpinnerCode.getCodeByStart(range.getStart());
    tf.selectRange(code.getStart(), code.getEnd());
    CURRENT_INDEX = code.getIndex();
    ldtsvf.setTemporalUnit(code.getChronoUnit());
}

/**
 * 若没有通过之前验证,字符串替换为0+arg0.getCharacter()
 *
 * @param code
 * @param arg0
 */
private void keyBoardingElse(LocalDateTimeSpinnerCode code, KeyEvent arg0) {
    CURRENT++;
    getEditor().replaceText(code.getStart(), code.getEnd(), 0 + arg0.getCharacter());
}

/**
 * 键入验证
 *
 * @param code
 * @param regex
 * @param arg0
 * @return
 */
private boolean keyBoardingRegex(LocalDateTimeSpinnerCode code, String regex, KeyEvent arg0) {
    if (getEditor().getText(code.getEnd() - 1, code.getEnd()).matches(regex)) {
        CURRENT++;
        getEditor().replaceText(code.getStart(), code.getEnd(),
                getEditor().getText(code.getEnd() - 1, code.getEnd()) + arg0.getCharacter());
        return true;
    }
    return false;
}

private void init() {

    ldtsvf.setPattern("yyyy-MM-dd HH:mm");
    setValueFactory(ldtsvf);
    // 初始化,值为空
    getValueFactory().setValue(null);
    setOnKeyPressed(new EventHandler() {
        @Override
        public void handle(KeyEvent event) {
            switch (event.getCode()) {
            case LEFT:
                focusLeft();
                // 此处可能被其他捕获
                event.consume();
                break;
            case RIGHT:
                focusRight();
                // 此处可能被其他捕获
                event.consume();
                break;
            case DELETE:
                getEditor().setText("");
                setDate(null);
                break;
            case BACK_SPACE:
                getEditor().setText("");
                setDate(null);
                break;
            default:
                break;
            }
        }
    });
    this.getEditor().setOnMouseClicked(new EventHandler() {
        @Override
        public void handle(MouseEvent event) {
            switchTemporalUnitByDoubleClick();
        }
    });
    valueProperty().addListener(new ChangeListener() {
        @Override
        public void changed(ObservableValue observable, LocalDateTime oldValue,
                LocalDateTime newValue) {
            if (CURRENT == 2) {
                if (!isMinute) {
                    focusRight();
                    CURRENT = 0;
                } else {
                    focusLeft();
                    isMinute = false;
                    CURRENT = 0;
                }
            } else {
                switchTemporalUnit();
            }
        }
    });
    /**
     * 控制键入
     */
    this.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler() {

        @Override
        public void handle(KeyEvent event) {
            IndexRange range = getEditor().getSelection();
            LocalDateTimeSpinnerCode code = LocalDateTimeSpinnerCode.getCodeByStart(range.getStart());
            if(getEditor().getText()==null){
                return;
            }
            if (event.getCharacter().matches("[0-9]")) {
                switch (code.getStart()) {
                case 0:
                    if(code.getEnd()<0||code.getEnd()>getEditor().getText().length()){
                        break;
                    }
                    if (getEditor().getText(code.getEnd() - 1, code.getEnd()).matches("[0-9]")) {
                        getEditor().replaceText(code.getStart() + 2, code.getEnd(),
                                getEditor().getText(code.getEnd() - 1, code.getEnd()) + event.getCharacter());
                    }
                    break;
                case 5:
                    if (!keyBoardingRegex(code, "1", event)) {
                        keyBoardingElse(code, event);
                    }
                    break;
                case 8:
                    if (!keyBoardingRegex(code, "[1-3]", event)) {
                        keyBoardingElse(code, event);
                    }
                    break;
                case 11:
                    if (!keyBoardingRegex(code, "[1-2]", event)) {
                        keyBoardingElse(code, event);
                    }
                    break;
                case 14:
                    isMinute = true;
                    if (!keyBoardingRegex(code, "[1-5]", event)) {
                        keyBoardingElse(code, event);
                    }
                    break;
                }
            }
            setDate(LocalDateConvert.getDate(getEditor().getText(), "yyyy-MM-dd HH:mm"));
        }
    });
    setPrefWidth(180);
}

public void focusLeft() {
    int count = ldtsvf.getPattern().split("\\-| |:").length;
    CURRENT_INDEX--;
    if (CURRENT_INDEX == 0) {
        CURRENT_INDEX = count;
    }
    switchTemporalUnit();
}

public void focusRight() {
    int count = ldtsvf.getPattern().split("\\-| |:").length;
    if (CURRENT_INDEX == count) {
        CURRENT_INDEX = 0;
    }
    CURRENT_INDEX++;
    switchTemporalUnit();
}

}

你可能感兴趣的:(javafx)