Используя в качестве отправной точки класс DecimalField, найденный на этом сайте, я написал следующее:
import javafx.scene.control.TextField;
import java.util.regex.Pattern;
public class DecimalField extends TextField {
public Boolean rate, positive, integer;
Pattern decimalPattern;
DecimalField(Boolean rate, Boolean positive) {
this.rate = rate;
this.positive = positive;
decimalPattern = Pattern.compile ("[-+]?[0-9]*(\\.[0-9]*)?");
// decimalPattern = Pattern.compile("[-+]?(\\b[0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+\\b)?");
if (rate) {
decimalPattern = Pattern.compile ("[-+]?[0-9]*(\\.[0-9]*)?[%]?");
} else if (positive) {
decimalPattern = Pattern.compile ("[1-9][0-9]*(\\.[0-9]*)?");
}
}
@Override
public void replaceText(int start, int end, String text) {
if (validate (start, text)) {
super.replaceText (start, end, text);
}
}
@Override
public void replaceSelection(String text) {
if (validate (Integer.MAX_VALUE, text)) {
super.replaceSelection (text);
}
}
private boolean validate(int start, String text) {
String currentText = (getText ().isEmpty ()) ? "" : getText ();
if (start == 0) { //to handle "-1.1" or ".1" cases
return decimalPattern.matcher (text + currentText).matches ();
} else {
return decimalPattern.matcher (currentText + text).matches ();
}
}
}
В зависимости от параметров, отправленных в конструктор, этот класс можно использовать для ограничения записей стандартным десятичное число, только положительное (т. е.> 0) десятичное число или число, за которым следует символ процента. Кажется, он работает нормально (предоставляется небольшое тестовое приложение), но я также хотел иметь возможность указать число в нотации scientifi c, например 25.56e-5. Я не мог написать правильный шаблон регулярного выражения. Такой шаблон, как «[0-9.eE + -] *» ограничил бы ввод допустимыми символами, но не обеспечил бы принудительный синтаксис числа! Предложения приветствуются.
Вот тестовая программа:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class DecimalFieldTest extends Application {
@Override
public void start(Stage primaryStage) {
// Boolean rate;
// rate = false; positive = true;
Label basicLbl = new Label("Basic Decimal");
DecimalField decimalField = new DecimalField (false, false);
Label rateLbl = new Label("Rate Decimal");
DecimalField rateDecimalField = new DecimalField (true, false);
Label positiveLbl = new Label("Positive Decimal");
DecimalField positiveDecimalField = new DecimalField (false, true);
Button clickMe = new Button ("Click Me");
clickMe.setOnAction (new EventHandler<ActionEvent> () {
@Override
public void handle(ActionEvent event) {
String s;
s = decimalField.getText ();
if (!s.isEmpty ()) getOut(s, false);
s = rateDecimalField.getText ();
if (!s.isEmpty ()) getOut(s, true);
s = positiveDecimalField.getText ();
if (!s.isEmpty ()) getOut(s, false);
}
});
decimalField.setOnAction (new EventHandler<ActionEvent> () {
@Override
public void handle(ActionEvent event) {
getOut(decimalField.getText (),false);
}
});
rateDecimalField.setOnAction (new EventHandler<ActionEvent> () {
@Override
public void handle(ActionEvent event) {
getOut(rateDecimalField.getText (),true);
}
});
positiveDecimalField.setOnAction (new EventHandler<ActionEvent> () {
@Override
public void handle(ActionEvent event) {
getOut(positiveDecimalField.getText (),false);
}
});
VBox root = new VBox (5, basicLbl, decimalField,
rateLbl, rateDecimalField, positiveLbl, positiveDecimalField, clickMe);
root.setAlignment (Pos.CENTER);
Scene scene = new Scene (root, 300, 250);
primaryStage.setScene (scene);
primaryStage.show ();
}
void getOut(String s, Boolean rate) {
// for rate : textField.getText().replaceAll("%","")
String ss = s.replaceAll ("%", "");
double value = Double.parseDouble (ss);
if (rate) {
System.out.println (String.format (ss + " <-> " + value) + "%");
} else {
System.out.println (String.format (ss + " <-> " + value));
}
}
public static void main(String[] args) {
launch (args);
}
}