2013-06-19 3 views
2

В текстовом поле я хочу, чтобы выполнить операцию следующим образом:Текста проверка поля в JavaFX

-> по умолчанию текст 00:00:00 устанавливается на время как текстовое поле для времени и длина символа поля равна 8.

-> если курсор находится в положении 0 (ноль), и если я нажимаю цифровую клавишу, он должен заменить значение позиции 0 и переместить курсор в следующую позицию.

eg : 00:00:00 
     20:00:00 

объяснение: теперь курсор г в положении 0 и я нажать клавишу 2 следует заменить значение 0 в положении 0 и переместиться в положение 1

, когда я нажимаю любой нечисловой ключ, как надо не заменяйте какое-либо значение, но курсор должен перейти в следующую позицию.

+0

Что вы пробовали? Через две недели вы наверняка внедрили какой-то подход? – Devolus

+0

Если вам нужен контроль уровня символов над форматом TextField, вам нужно обработать KeyEvents на TextField. Хотя это можно сделать полностью в контроллере для вашего графического интерфейса, вы также захотите рассмотреть возможность создания настраиваемого элемента управления TextField для этой цели. – scottb

ответ

2

Это отлично работает:

import java.util.regex.Pattern; 
    import javafx.application.Application; 
    import javafx.beans.binding.Bindings; 
    import javafx.beans.binding.IntegerBinding; 
    import javafx.beans.property.ReadOnlyIntegerProperty; 
    import javafx.beans.property.ReadOnlyIntegerWrapper; 
    import javafx.geometry.Insets; 
    import javafx.scene.Scene; 
    import javafx.scene.control.IndexRange; 
    import javafx.scene.control.Label; 

import javafx.scene.control.TextField; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
public class TimeTextFieldTest extends Application { 
@Override 
    public void start(Stage primaryStage) { 
    VBox root = new VBox(5); 
    root.setPadding(new Insets(5)); 
    Label hrLabel = new Label(); 
    Label minLabel = new Label(); 
    Label secLabel = new Label(); 
    TimeTextField timeTextField = new TimeTextField(); 
    hrLabel.textProperty().bind(Bindings.format("Hours: %d", timeTextField.hoursProperty())); 
    minLabel.textProperty().bind(Bindings.format("Minutes: %d", timeTextField.minutesProperty())); 
    secLabel.textProperty().bind(Bindings.format("Seconds: %d", timeTextField.secondsProperty())); 
    root.getChildren().addAll(timeTextField, hrLabel, minLabel, secLabel); 
    Scene scene = new Scene(root); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
    } 
    public static void main(String[] args) { 
    launch(args); 
    } 
    public static class TimeTextField extends TextField { 

    enum Unit {HOURS, MINUTES, SECONDS}; 
    private final Pattern timePattern ; 
    private final ReadOnlyIntegerWrapper hours ; 
    private final ReadOnlyIntegerWrapper minutes ; 
    private final ReadOnlyIntegerWrapper seconds ; 

    public TimeTextField() { 
     this("00:00:00"); 
    } 
    public TimeTextField(String time) { 
     super(time); 
     timePattern = Pattern.compile("\\d\\d:\\d\\d:\\d\\d"); 
     if (! validate(time)) { 
     throw new IllegalArgumentException("Invalid time: "+time); 
     } 
     hours = new ReadOnlyIntegerWrapper(this, "hours"); 
     minutes = new ReadOnlyIntegerWrapper(this, "minutes"); 
     seconds = new ReadOnlyIntegerWrapper(this, "seconds"); 
     hours.bind(new TimeTextField.TimeUnitBinding(Unit.HOURS)); 
     minutes.bind(new TimeTextField.TimeUnitBinding(Unit.MINUTES)); 
     seconds.bind(new TimeTextField.TimeUnitBinding(Unit.SECONDS)); 
    } 

    public ReadOnlyIntegerProperty hoursProperty() { 
     return hours.getReadOnlyProperty(); 
    } 

    public int getHours() { 
     return hours.get() ; 
    } 

    public ReadOnlyIntegerProperty minutesProperty() { 
     return minutes.getReadOnlyProperty(); 
    } 

    public int getMinutes() { 
     return minutes.get(); 
    } 

    public ReadOnlyIntegerProperty secondsProperty() { 
     return seconds.getReadOnlyProperty(); 
    } 

    public int getSeconds() { 
     return seconds.get(); 
    } 

    @Override 
    public void appendText(String text) { 
     // Ignore this. Our text is always 8 characters long, we cannot append anything 
    } 

    @Override 
    public boolean deleteNextChar() { 
     boolean success = false ; 

     // If there's a selection, delete it: 
     final IndexRange selection = getSelection(); 
     if (selection.getLength()>0) { 
     int selectionEnd = selection.getEnd(); 
     this.deleteText(selection); 
     this.positionCaret(selectionEnd); 
     success = true ; 
     } else { 
     // If the caret preceeds a digit, replace that digit with a zero and move the caret forward. Else just move the caret forward. 
     int caret = this.getCaretPosition(); 
     if (caret % 3 != 2) { // not preceeding a colon 
     String currentText = this.getText(); 
     setText(currentText.substring(0, caret) + "0" + currentText.substring(caret+1)); 
     success = true ; 
     } 
     this.positionCaret(Math.min(caret+1, this.getText().length())); 
     } 
     return success ; 
    } 

    @Override 
    public boolean deletePreviousChar() { 
     boolean success = false ; 
     // If there's a selection, delete it: 
     final IndexRange selection = getSelection(); 
     if (selection.getLength()>0) { 
     int selectionStart = selection.getStart(); 
     this.deleteText(selection); 
     this.positionCaret(selectionStart); 
     success = true ; 
     } else { 
     // If the caret is after a digit, replace that digit with a zero and move the caret backward. Else just move the caret back. 
     int caret = this.getCaretPosition(); 
     if (caret % 3 != 0) { // not following a colon 
      String currentText = this.getText(); 
      setText(currentText.substring(0, caret-1) + "0" + currentText.substring(caret)); 
      success = true ; 
     } 
     this.positionCaret(Math.max(caret-1, 0)); 
     } 
     return success ; 
    } 

    @Override 
    public void deleteText(IndexRange range) { 
     this.deleteText(range.getStart(), range.getEnd()); 
    } 

    @Override 
    public void deleteText(int begin, int end) { 
     // Replace all digits in the given range with zero: 
     StringBuilder builder = new StringBuilder(this.getText()); 
     for (int c = begin; c<end; c++) { 
     if (c % 3 != 2) { // Not at a colon: 
      builder.replace(c, c+1, "0"); 
     } 
     } 
     this.setText(builder.toString()); 
    } 

    @Override 
    public void insertText(int index, String text) { 
     // Handle an insert by replacing the range from index to index+text.length() with text, if that results in a valid string: 
     StringBuilder builder = new StringBuilder(this.getText()); 
     builder.replace(index, index+text.length(), text); 
     final String testText = builder.toString(); 
     if (validate(testText)) { 
     this.setText(testText); 
     } 
     this.positionCaret(index + text.length()); 
    } 

    @Override 
    public void replaceSelection(String replacement) { 
     final IndexRange selection = this.getSelection(); 
     if (selection.getLength()==0) { 
     this.insertText(selection.getStart(), replacement); 
     } else { 
     this.replaceText(selection.getStart(), selection.getEnd(), replacement); 
     } 
    } 

    @Override 
    public void replaceText(IndexRange range, String text) { 
     this.replaceText(range.getStart(), range.getEnd(), text); 
    } 

    @Override 
    public void replaceText(int begin, int end, String text) { 
     if (begin==end) { 
     this.insertText(begin, text); 
     } else { 
     // only handle this if text.length() is equal to the number of characters being replaced, and if the replacement results in a valid string: 
     if (text.length() == end - begin) { 
     StringBuilder builder = new StringBuilder(this.getText()); 
     builder.replace(begin, end, text); 
     String testText = builder.toString(); 
     if (validate(testText)) { 
      this.setText(testText); 
     } 
      this.positionCaret(end); 
     } 
     } 
    } 

    private boolean validate(String time) { 
     if (! timePattern.matcher(time).matches()) { 
     return false ; 
     } 
     String[] tokens = time.split(":"); 
     assert tokens.length == 3 ; 
     try { 
     int hours = Integer.parseInt(tokens[0]); 
     int mins = Integer.parseInt(tokens[1]); 
     int secs = Integer.parseInt(tokens[2]); 
     if (hours < 0 || hours > 23) { 
      return false ; 
     } 
     if (mins < 0 || mins > 59) { 
      return false ; 
     } 
     if (secs < 0 || secs > 59) { 
      return false ; 
     } 
     return true ; 
     } catch (NumberFormatException nfe) { 
     // regex matching should assure we never reach this catch block 
     assert false ; 
     return false ; 
     } 
    } 

    private final class TimeUnitBinding extends IntegerBinding { 

     final Unit unit ; 
     TimeUnitBinding(Unit unit) { 
     this.bind(textProperty()); 
     this.unit = unit ; 
     } 
     @Override 
     protected int computeValue() { 
     // Crazy enum magic 
     String token = getText().split(":")[unit.ordinal()]; 
     return Integer.parseInt(token); 
     } 

    } 

    } 
} 
+0

@tarrsalah отличный мужчина !!! –

1

Я бы зарегистрировал прослушиватель событий для событий с типизированным типом, например.

myTextField.setOnKeyTyped(new EventListener<KeyEvent>() { ...handler_code... }); 

Этот слушатель скажет вам, что только что напечатали, и вы должны иметь доступ к текстовому полю в слушателе, так что вы можете определить положение курсора. Это должна быть вся необходимая информация.

Например, если пользователь вводит число, удалите символ справа от каретки, и если пользователь нажимает нечисловой ключ, удалите символ слева от каретки. Дополнительная проверка будет необходима для обработки двоеточий и конца строки.

Смежные вопросы