I want let the user can only input 3 digit。
I try to use [0,9]{0,3} to make sure the input can not be more than 3 digit, however, the [0,9] part work, i can not input sth like abcd, but the {0,3}part doesn't work, i can input more than 3 number such as 123456
TextField textArea1 = new TextField();
textArea1.setTextFormatter(new TextFormatter<String>(new UnaryOperator<TextFormatter.Change>() {
#Override
public TextFormatter.Change apply(TextFormatter.Change change) {
String value = change.getText();
if(value.matches("[0-9]{0,3}"))
{
return change;
}
return null;
}
}));
Return the change if the change is zero or more digits and the control's text length is less than or equal to 3.
TextField textArea1 = new TextField();
UnaryOperator<Change> integerFilter = change -> {
System.out.println(change);
if (change.getText().matches("\\d*") && change.getControlNewText().length() <= 3) {
return change;
}
return null;
};
If you want to use Matches only, you need to use getControlNewText().
TextField textArea1 = new TextField();
UnaryOperator<Change> integerFilter = change -> {
System.out.println(change);
if (change.getControlNewText().matches("[0-9]{0,3}")) {
return change;
}
return null;
};
Related
I created a simple javafx program. I want to seprate the digits three by three when I entering the digits in the textfiled. I used two solution which are given in the stackoverflow links(How to format text of TextField? JavaFX , Java 8 U40 TextFormatter (JavaFX) to restrict user input only for decimal number)
but none them are working for me. the first solution(set textformatter) was useless for me(or maybe I couldn't work with it in a right way) but the second one was working but only accept 4 digits and the other numbers that I enterd in the textfield are the in the same style that I enterd them without comma.
I want to seprate every three digits like this: 12,564,546,554
if anyone know the solution please help me to overcome this problem.
thanks.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import java.text.DecimalFormat;
import java.text.ParsePosition;
public class DelimiterExample extends Application{
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField();
HBox hBox = new HBox();
//solution one
DecimalFormat format = new DecimalFormat( "#,###" );
textField.setTextFormatter( new TextFormatter<>(c ->
{
if ( c.getControlNewText().isEmpty() )
{
return c;
}
ParsePosition parsePosition = new ParsePosition( 0 );
Object object = format.parse( c.getControlNewText(), parsePosition );
if ( object == null || parsePosition.getIndex() < c.getControlNewText().length() )
{
return null;
}
else
{
return c;
}
}));
// solution two
textField.textProperty().addListener((obs , oldVal , newVal)-> {
if (newVal.matches("\\d*")) {
DecimalFormat formatter = new DecimalFormat("#,###");
String newvalstr = formatter.format(Float.parseFloat(newVal));
//System.out.println(newvalstr);
textField.setText(newvalstr);
}
});
hBox.getChildren().add(textField);
Scene scene = new Scene(hBox , 100 , 100);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Any modification that is not a selection change can be fixed by modifying the chars before the range:
final char seperatorChar = ',';
final Pattern p = Pattern.compile("[0-9" + seperatorChar + "]*");
textField.setTextFormatter(new TextFormatter<>(c -> {
if (!c.isContentChange()) {
return c; // no need for modification, if only the selection changes
}
String newText = c.getControlNewText();
if (newText.isEmpty()) {
return c;
}
if (!p.matcher(newText).matches()) {
return null; // invalid change
}
// invert everything before the range
int suffixCount = c.getControlText().length() - c.getRangeEnd();
int digits = suffixCount - suffixCount / 4;
StringBuilder sb = new StringBuilder();
// insert seperator just before caret, if necessary
if (digits % 3 == 0 && digits > 0 && suffixCount % 4 != 0) {
sb.append(seperatorChar);
}
// add the rest of the digits in reversed order
for (int i = c.getRangeStart() + c.getText().length() - 1; i >= 0; i--) {
char letter = newText.charAt(i);
if (Character.isDigit(letter)) {
sb.append(letter);
digits++;
if (digits % 3 == 0) {
sb.append(seperatorChar);
}
}
}
// remove seperator char, if added as last char
if (digits % 3 == 0) {
sb.deleteCharAt(sb.length() - 1);
}
sb.reverse();
int length = sb.length();
// replace with modified text
c.setRange(0, c.getRangeEnd());
c.setText(sb.toString());
c.setCaretPosition(length);
c.setAnchor(length);
return c;
}));
Please guys don't reinvent the wheel. The class javafx.util.converter.NumberStringConverter do all the needed work for us:
TextField numberField = new TextField();
TextFormatter<Number> textFormatter = new TextFormatter<>(new NumberStringConverter());
numberField.setTextFormatter(textFormatter);
NumberStringConverter is your friend ;), if you want to listen the correct number changes on the textfield, simply use the next textFormatter property (forgive direct method invocations over the textField object):
textFormatter.valueProperty(); //Returns ObjectProperty<Number>
Then you can retrieve any kind of number subclass (number.intValue(), number.floatValue(), etc), and the ChangeListener only will be triggered when the user writes a valid numeric value.
If you want to manually set a number value to the textfield:
float value = 1000f; //or any type of Number subclass
textFormatter.setValue(value);
P.D: NumberStringConverter has a Locale attribute that can be changed to apply the appropriate format of the desired Country.
Thanks again #fabian.I stucked in this problem for two days. I also found that I can have the currency style that I want with this code.Now I have two perfect solution.
textField.setOnKeyTyped(event -> {
String typedCharacter = event.getCharacter();
event.consume();
if (typedCharacter.matches("\\d*")) {
String currentText =
textField.getText().replaceAll("\\.","").replace(",", "");
long longVal = Long.parseLong(currentText.concat(typedCharacter));
textField.setText(new DecimalFormat("#,##0").format(longVal));
}
});
I am trying to format string in TextField which includes: remove all characters that are not numbers, format numbers using DecimalFormatter and limit number of character in the TextField:
private void IntegerInputChecker() {
ChangeListener<String> integerChecker = new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue,
String newValue) {
String pureValue = newValue;
String formatedText = newValue;
if (pureValue.length() <= 15) {
// Limit the characters in TextField
if (!newValue.matches("\\d*")) {
// Replace everything excepts number
pureValue = newValue.replaceAll("[^\\d]", "");
formatedText = pureValue;
}
if (pureValue.length() > 3) {
// Format number
DecimalFormat formatter = new DecimalFormat( "#,###" );
formatedText = formatter.format(Double.parseDouble(pureValue));
}
else if(pureValue.length() == 3) {
formatedText = pureValue.replaceAll(",", "");
}
}
else {
// Limit the characters in TextField
formatedText = formatedText.substring(0, formatedText.length() - 1);
}
fieldPrice.setText(formatedText);
}
};
fieldPrice.textProperty().addListener(integerChecker);
}
Everything works fine when I type in number but when I try to delete them in order, JavaFX throws an exception (the program still works fine):
java.lang.IllegalArgumentException: The start must be <= the end
For example, If I have 123,456,789 when I delete the number to 123,456 then it throws the above exception.
Thanks in advance.
I am working on an assignment, but I cannot seem to get my text to print out in the TextArea. I'm working on using recursive methods,and I need to send the result from the recursive method to the TextArea. I have tried multiple things and it has not worked, and searched the web to no avail. Please help!
public class Sheppard_Week5 extends Application {
Button convert = new Button("Convert");
Button clear = new Button("Clear");
Button exitBtn = new Button("Exit");
Label enterInt = new Label("Enter Number:");
TextField enterText = new TextField();
TextArea binaryText = new TextArea();
ImageView mCEscher = new ImageView("sheppard_week5/M.C.Escher.jpg");
ArrayList<String> remainderList = new ArrayList();
ScrollPane scrollPane = new ScrollPane(binaryText)
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane bPane = new BorderPane();
GridPane gPane = new GridPane();
gPane.setStyle("-fx-background-color: #fffaf0;");
bPane.setStyle("-fx-background-color: #fffaf0;");
bPane.setCenter(gPane);
Scene scene = new Scene(bPane);
bPane.setBottom(buttonBox());
bPane.setTop(titleBox());
mCEscher.setFitHeight(300);
mCEscher.setFitWidth(300);
for (int i = 0; i <= 3; i++) {
ColumnConstraints column = new ColumnConstraints();
column.setPercentWidth(25);
gPane.getColumnConstraints().add(column);
}
/*Gridpane
*GridPane.setConstraints(node, column Index, row Index, column span, row span);
*/
gPane.add(enterInt, 0, 0);
gPane.add(enterText, 1, 0);
gPane.add(binaryText, 2, 0);
GridPane.setConstraints(binaryText, 2, 0, 2, 4);
gPane.add(mCEscher, 0, 1);
GridPane.setColumnSpan(mCEscher, 2);
binaryText.setEditable(false);
scrollPane.setContent(binaryText);
primaryStage.setTitle("Binary Converter");
primaryStage.setScene(scene);
primaryStage.show();
}
private VBox titleBox() throws Exception{
VBox titlesBox = new VBox();
Text title = new Text("Welcome to GUI #5");
title.setStyle("-fx-text-fill: #000000");
title.setFont(Font.font("Monospace",FontWeight.NORMAL, FontPosture.REGULAR, 30));
Text subtitle = new Text("I think this class will be the death of me, "
+ "\nI really wish I could get one thing right...");
subtitle.setFont(Font.font("Monospace", FontWeight.NORMAL, FontPosture.ITALIC, 10));
subtitle.setStyle("-fx-text-fill: #000000");
Text subsubtitle = new Text("Please enter an integer.");
subsubtitle.setFont(Font.font("Monospace", FontWeight.NORMAL, FontPosture.ITALIC, 7));
subsubtitle.setStyle("-fx-text-fill: #000000");
Text subsubsubtitle = new Text("Please dear God work");
subsubsubtitle.setFont(Font.font("Monospace", FontWeight.NORMAL, FontPosture.ITALIC, 3));
subsubsubtitle.setStyle("-fx-text-fill: #000000");
titlesBox.setAlignment(Pos.TOP_CENTER);
titlesBox.getChildren().addAll(title, subtitle, subsubtitle, subsubsubtitle);
return titlesBox;
}
private HBox buttonBox() throws Exception{
HBox buttbox = new HBox();
buttbox.getChildren().addAll(convert, clear, exitBtn);
buttbox.setAlignment(Pos.CENTER);
buttbox.setMargin(clear,new Insets(10,10,10,10));
convert.setOnAction(new convertHandler());
clear.setOnAction(new resetHandler());
exitBtn.setOnAction(e ->{
Platform.exit();
});
return buttbox;
}
class convertHandler implements EventHandler<ActionEvent>{
#Override
public void handle(ActionEvent event){
if (enterText.getText().trim().isEmpty()){
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Warning");
alert.setHeaderText("Required Fields Empty");
alert.setContentText("You must enter an integer.\n"
+ "Please try again.");
alert.showAndWait();
}
else if (!enterText.getText().trim().isEmpty()){
try {
Integer.parseInt(enterText.getText());
} catch (NumberFormatException nfe){
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Warning");
alert.setHeaderText("Field is not an integer");
alert.setContentText("The entered text is not an integer.\n"
+ "Please try again.");
alert.showAndWait();
}
} else {
int enteredNumb = Integer.parseInt(enterText.getText());
ToBinary(enteredNumb);
Collections.reverse(remainderList);
binaryText.appendText("-------------------------------\n");
for (int i = 0; i < remainderList.size(); i++){
binaryText.setText(remainderList.get(i));
}
}
}
}
class resetHandler implements EventHandler<ActionEvent>{
#Override
public void handle(ActionEvent event){
remainderList.clear();
binaryText.clear();
enterText.clear();
}
}
public int ToBinary(int number) {
/* Define variable required in method */
if (number == 0) {
return 0;
} else {
int remainder = number - 2 * (number / 2);
String remainderString = Integer.toString(remainder);
String numberString = Integer.toString(number);
remainderList.add(remainderString);
String number2String = Integer.toString(number);
binaryText.appendText(numberString + "/2= " + number2String + " Remainder "
+ remainderString + "\n");
ToBinary(number / 2); //Recurrsive call to method
}
return number;
}
} //End Class Sheppard_Week5
You simply never reach the call of the ToBinary method in convertHandler.handle:
if (enterText.getText().trim().isEmpty()){
doA();
}
else if (!enterText.getText().trim().isEmpty()){
doB();
} else {
doC();
}
can have exactly 3 outcomes:
An exception is thrown by enterText.getText().trim().isEmpty(), e.g. a NullPointerException and the code proceeds with the next surrounding catch block with an appropriate catch clause.
enterText.getText().trim().isEmpty() yields true and doA() is executed
enterText.getText().trim().isEmpty() yields false and doB() is executed
since your call to toBinary is in the doC() part, it's never executed. If you need to proceed if parsing succeeds you need to do this in the try block or exit the method in the catch block and put the logic from the last else right behind the last catch:
try {
int enteredNumb = Integer.parseInt(enterText.getText());
ToBinary(enteredNumb);
Collections.reverse(remainderList);
binaryText.appendText("-------------------------------\n");
for (int i = 0; i < remainderList.size(); i++){
binaryText.setText(remainderList.get(i));
}
} catch (NumberFormatException nfe){
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Warning");
alert.setHeaderText("Field is not an integer");
alert.setContentText("The entered text is not an integer.\n"
+ "Please try again.");
alert.showAndWait();
}
or
int enteredNumb;
try {
enteredNumb = Integer.parseInt(enterText.getText());
} catch (NumberFormatException nfe){
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Warning");
alert.setHeaderText("Field is not an integer");
alert.setContentText("The entered text is not an integer.\n"
+ "Please try again.");
alert.showAndWait();
return;
}
ToBinary(enteredNumb);
Collections.reverse(remainderList);
binaryText.appendText("-------------------------------\n");
for (int i = 0; i < remainderList.size(); i++){
binaryText.setText(remainderList.get(i));
}
Additional notes:
int remainder = number - 2 * (number / 2);
there already is a way to do this in a single operation:
int remainder = number % 2;
In this case assuming non-negative number it can also be optimized using a binary operator which should be a bit faster than the remainder operator:
int remainder = number & 1; // extract least significant bit
I guess you're supposed to return something different from the ToBinary method. Otherwise you could easily use void as return type.
If you want the remainders to be ordered from the most significant to the least significant bits, you need to do the recursive call before adding to the list. This way you don't need to reverse the list after the initial call to toBinary.
You need to call remainderList.clear() unless you require the user to click the clear button between clicks on the convert button. Otherwise the list will still contain the last results.
I want to make a calculator. I have an array to store my value in it . I have two text fields (text1 and text2) where text1 refer to array[0] and text2 refer to array[1] .. when I insert number 1 in text1 and insert number 2 in text2 , then I get 3 as output but when I insert number 12 in text1 and I insert number 22 in text2 then I still get output 3 , this means that the calculator add 1+2 but not 12+22 .. How can I get the whole value in text1 and text2 to add them together? I mean I want the output should be 12+22=34 ...thanks
stack class
int[] array = new int[4];
public enum Operation {
PLUS
}
public void CalculateSign(Operation op) {
switch (op) {
case PLUS:
result = (array[0] + array[1]);
//array[0] = result;
System.out.println(array[0]);
System.out.println(array[1]);
break;
}
public void Number(int nbr) {
array[0] = nbr;
}
calculator class
TextField text1 = new TextField();
TextField text2 = new TextField();
plusButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (event.getSource() == plusButton) {
stack.CalculateSign(Stack.Operation.PLUS);
text1.setText(Integer.toString(stack.result));
}
}
});
one.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (event.getSource() == one) {
stack.Number(1); text1.setText(text1.getText()+String.valueOf(stack.array[0]));
}
}
});
two.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (event.getSource() == two) {
stack.Number(2);
text1.setText(text1.getText()+String.valueOf(stack.array[0]));
}
}
});
Your Number(int nbr) method sets the array cells to its parameter value. In your EventHandlers for your two TextFields you have hard-coded Number(1) and Number(2). Ergo, you will always add 1 and 2, regardless of the actal contents of text1 and text2.
I am trying to make an executable JButton (which opens a new window)radiobutton is chosen and the textfiled is filled within a specific range (the textfield should be from 1800 to 2013) . For the radiobuttons I made a default choise for now, but I cannot figure out how can I return a warning that the textfield should be filled (a number between 1800 and 2013) and if it is there then it run the program.
EDIT:
So if my code is:
JFrame ....
JPanel ....
JTextField txt = new JTextField();
JButton button = new JButton("run");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
//Do things here
}
});
txt.addFocusListener(new FocusListener() {
....
}
how can I use the ItemStateListener. Should I define a listener and then what?
public void actionPerformed(ActionEvent e)
{
String s = txt.getText();
char[] cArr = s.toCharAray();
ArrayList<Character> chars = new ArrayList<Character>();
for (char c : cArr)
if (c.isDigit())
chars.add(c);
cArr = new char[chars.size()];
for (int i = 0;i<chars.size();i++)
cArr[i] = char.get(i);
s = new String(cArr);
txtField.setText(s);
if (s.equals(""))
{
// issue warning
return;
}
int input = Integer.parseInt(s);
if (input >= 1800 && input <= 2013)
{
// do stuff
}
}
Basically, read the string in the text field, remove all non-numeric characters from it, and only proceed if it is in the range specified.