2016-11-07 18 views
7

tôi đang cố gắng để tạo ra một TextField số cho số nguyên bằng công TextFormatter của JavaFX 8.TextField Numeric cho số nguyên trong JavaFX 8 với TextFormatter và/hoặc UnaryOperator

Giải pháp với UnaryOperator:

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

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

giải pháp với IntegerStringConverter:

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

Cả hai giải pháp đều có vấn đề riêng. Với UnaryOperator, tôi chỉ có thể nhập các chữ số từ 0 đến 9 như dự định, nhưng tôi cũng cần nhập các giá trị âm như "-512", trong đó ký hiệu chỉ được phép ở vị trí đầu tiên. Ngoài ra tôi không muốn những con số như "00016" mà vẫn còn có thể.

Phương pháp IntegerStringConverter hoạt động tốt hơn: Mọi số không hợp lệ như "-16-123" không được chấp nhận và các số như "0123" được chuyển thành "123". Nhưng chuyển đổi chỉ xảy ra khi văn bản được cam kết (thông qua nhấn enter) hoặc khi TextField mất tiêu điểm của nó.

Có cách nào để thực thi chuyển đổi phương thức thứ hai bằng IntegerStringConverter mỗi khi giá trị của TextField được cập nhật không?

Trả lời

13

Bộ chuyển đổi khác với bộ lọc: trình chuyển đổi chỉ định cách chuyển đổi văn bản thành giá trị và bộ lọc lọc các thay đổi mà người dùng có thể thực hiện. Có vẻ như ở đây bạn muốn cả hai, nhưng bạn muốn bộ lọc lọc chính xác hơn các thay đổi được cho phép.

Tôi thường tìm thấy nó dễ dàng nhất để kiểm tra giá trị mới của văn bản nếu thay đổi được chấp nhận. Bạn muốn tùy chọn có một số -, theo sau là 1-9 với bất kỳ số chữ số nào sau đó. Điều quan trọng là phải cho phép một chuỗi rỗng, nếu không người dùng sẽ không thể xóa mọi thứ.

Vì vậy, có thể bạn cần một cái gì đó giống như

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)); 

Bạn thậm chí có thể thêm nhiều chức năng hơn cho các bộ lọc để cho nó xử lý - theo một cách thông minh hơn, ví dụ

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; 
}; 

Điều này sẽ cho phép người dùng nhấn - tại bất kỳ thời điểm nào và nó sẽ chuyển đổi dấu của số nguyên.

SSCCE:

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

sử dụng thông minh của '' vào nhóm số?! Đã suy nghĩ về '-? ([1-9]? | [1-9] [0-9] *)', nhưng điều này sạch hơn nhiều! – flakes

+1

Tôi thực sự đánh giá cao nỗ lực của bạn, giải pháp của bạn đã hoạt động hoàn hảo! – 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

Trên ngăn xếp tràn một số lời giải thích/hướng dẫn sử dụng thường được hoan nghênh. – mkl

Các vấn đề liên quan