2016-11-07 60 views
7

Ben UnaryOperator ile JavaFX 8.Sayısal TextField ve/veya UnaryOperator

Çözüm TextFormatter kullanarak tamsayılar için sayısal TextField oluşturmaya çalışıyorum:

UnaryOperator<Change> integerFilter = change -> { 
    String input = change.getText(); 
    if (input.matches("[0-9]*")) { 
     return change; 
    } 
    return null; 
}; 

myNumericField.setTextFormatter(new TextFormatter<String>(integerFilter)); 
IntegerStringConverter ile

Çözüm:

myNumericField.setTextFormatter(new TextFormatter<>(new IntegerStringConverter())); 

Her iki çözüm de kendi sorunlarına sahiptir. UnaryOperator ile, ben sadece amaçlanan gibi 0 ile 9 arası rakamları girebilirsiniz, ama ben de işareti sadece ilk pozisyonda izin "-512" gibi negatif değerler girmeniz gerekir. Ayrıca hala mümkün olan "00016" gibi numaralar istemiyorum.

IntegerStringConverter yöntemi yolu daha iyi çalışır: "-16-123" "0123" gibi kabul ve sayılar edilmez gibi her geçersiz sayı "123" dönüştürülür. Ancak, dönüşüm yalnızca metin işlendiğinde (enter tuşuna basarak) veya TextField odağını kaybettiğinde gerçekleşir.

TextField değeri her güncellendiğinde ikinci yöntemin IntegerStringConverter ile dönüştürülmesini zorlamanın bir yolu var mı?

cevap

13

Dönüştürücü, filtreden farklıdır: dönüştürücü, metnin bir değere nasıl dönüştürüleceğini ve filtre filtrelerinin, kullanıcının yapacağı değişiklikleri değiştireceğini belirtir. Her ikisini de istediğiniz gibi görünüyor, ancak filtrenin izin verilen değişiklikleri daha doğru bir şekilde filtrelemesini istiyorsunuz.

Genellikle değişiklik kabul edildiği takdirde metnin yeni değerini kontrol yapmayı daha kolay bulabilirsiniz. Bunun ardından herhangi bir rakam ile 1-9 bir -, izlemiş isteğe istiyorum. Boş bir dizeye izin vermek önemlidir, aksi halde kullanıcı her şeyi silemez.

Yani muhtemelen

UnaryOperator<Change> integerFilter = change -> { 
    String newText = change.getControlNewText(); 
    if (newText.matches("-?([1-9][0-9]*)?")) { 
     return change; 
    } 
    return null; 
}; 

myNumericField.setTextFormatter(
    new TextFormatter<Integer>(new IntegerStringConverter(), 0, integerFilter)); 
Hatta o daha akıllı bir şekilde, örneğin - işlemeniz için filtreye başka işlevler ekleyebilirsiniz

gibi bir şey gerekiyor

UnaryOperator<Change> integerFilter = change -> { 
    String newText = change.getControlNewText(); 
    // if proposed change results in a valid value, return change as-is: 
    if (newText.matches("-?([1-9][0-9]*)?")) { 
     return change; 
    } else if ("-".equals(change.getText())) { 

     // if user types or pastes a "-" in middle of current text, 
     // toggle sign of value: 

     if (change.getControlText().startsWith("-")) { 
      // if we currently start with a "-", remove first character: 
      change.setText(""); 
      change.setRange(0, 1); 
      // since we're deleting a character instead of adding one, 
      // the caret position needs to move back one, instead of 
      // moving forward one, so we modify the proposed change to 
      // move the caret two places earlier than the proposed change: 
      change.setCaretPosition(change.getCaretPosition()-2); 
      change.setAnchor(change.getAnchor()-2); 
     } else { 
      // otherwise just insert at the beginning of the text: 
      change.setRange(0, 0); 
     } 
     return change ; 
    } 
    // invalid change, veto it by returning null: 
    return null; 
}; 

Bu

herhangi bir noktada kullanıcı basın - sağlayacak ve tamsayı işareti geçiş yapılır.

SSCCE: sayı grubu üzerinde `` arasında

import java.util.function.UnaryOperator; 

import javafx.application.Application; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.TextField; 
import javafx.scene.control.TextFormatter; 
import javafx.scene.control.TextFormatter.Change; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
import javafx.util.StringConverter; 
import javafx.util.converter.IntegerStringConverter; 

public class IntegerFieldExample extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     TextField integerField = new TextField(); 
     UnaryOperator<Change> integerFilter = change -> { 
      String newText = change.getControlNewText(); 
      if (newText.matches("-?([1-9][0-9]*)?")) { 
       return change; 
      } else if ("-".equals(change.getText())) { 
       if (change.getControlText().startsWith("-")) { 
        change.setText(""); 
        change.setRange(0, 1); 
        change.setCaretPosition(change.getCaretPosition()-2); 
        change.setAnchor(change.getAnchor()-2); 
        return change ; 
       } else { 
        change.setRange(0, 0); 
        return change ; 
       } 
      } 
      return null; 
     }; 

     // modified version of standard converter that evaluates an empty string 
     // as zero instead of null: 
     StringConverter<Integer> converter = new IntegerStringConverter() { 
      @Override 
      public Integer fromString(String s) { 
       if (s.isEmpty()) return 0 ; 
       return super.fromString(s); 
      } 
     }; 

     TextFormatter<Integer> textFormatter = 
       new TextFormatter<Integer>(converter, 0, integerFilter); 
     integerField.setTextFormatter(textFormatter); 

     // demo listener: 
     textFormatter.valueProperty().addListener((obs, oldValue, newValue) -> System.out.println(newValue)); 

     VBox root = new VBox(5, integerField, new Button("Click Me")); 
     root.setAlignment(Pos.CENTER); 
     Scene scene = new Scene(root, 300, 120); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+1

Akıllı kullanım! düşünüyordum '- ([1-9] | [1-9] [0-9] *?)?', ama bu daha temiz! – flakes

+1

Çabalarınızı takdir ediyorum, çözümünüz mükemmel çalıştı! – ShadowEagle

1
TextField txtpoint = new TextField(); 
    txtpoint.textProperty().addListener(new ChangeListener<String>() { 
     @Override 
     public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { 
      if (!newValue.isEmpty()) { 
       try { 
        long pointI = Integer.parseInt(newValue); 
        txtpoint.setText(String.valueOf(pointI)); 
       } catch (Exception e) { 
        txtpoint.clear(); 
        txtpoint.setText(getNumber(oldValue)); 
       } 
      } 
     } 
    }); 


private String getNumber(String value) { 
    String n = ""; 
    try { 
     return String.valueOf(Integer.parseInt(value)); 
    } catch (Exception e) { 
     String[] array = value.split(""); 
     for (String tab : array) { 
      try { 
       System.out.println(tab); 
       n = n.concat(String.valueOf(Integer.parseInt(String.valueOf(tab)))); 
      } catch (Exception ex) { 
       System.out.println("not nomber"); 
      } 
     } 
     return n; 
    } 
} 
+1

yığın taşması üzerine açıklama/kullanım talimatının bazı kelimeler genellikle karşılanır. – mkl