gpt4 book ai didi

javafx-8 - 如何在 TextField 中格式化字符串而不用 JavaFX 更改它的值

转载 作者:行者123 更新时间:2023-12-01 00:41:11 25 4
gpt4 key购买 nike

我正在尝试更改 TextField 的值仅供展示。即 - 当用户尝试输入电话号码时,他们只输入数字,当他们离开该字段时,它显示格式化而不更改字段中的数据。

假设我有一个 TextField对于电话号码,它应该只允许数字,最多 10 个字符:

2085551212

我可以用 TextFormatter 处理它使用 UnaryOperator .

 UnaryOperator<TextFormatter.Change> filter = new UnaryOperator<TextFormatter.Change>() {
@Override
public TextFormatter.Change apply(TextFormatter.Change change) {
int maxlength = 14;

if(change.getControlText().indexOf('(') == -1) {
maxlength = 10;
}

System.out.println(change);

if (change.getControlText().length() + change.getText().length() >= maxlength) {
int maxPos = maxlength - change.getControlText().length();
change.setText(change.getText().substring(0, maxPos));
}

String text = change.getText();

for (int i = 0; i < text.length(); i++)
if (!Character.isDigit(text.charAt(i)))
return null;

return change;
}
};

但是,我想将值格式化为 10 个字符长(当 != 10 时可能未格式化):

(208) 555-1212

当我使用 TextFormatter为了格式化它,它将字符串的值更改为 (208) 555-1212。我们仅将数字存储在数据库 2085551212 中。

我尝试使用 StringConverter .但我无法让它工作。在 toString()方法我去掉格式,但是当我这样做时,我的 TextField不显示。
 StringConverter<String> formatter = new StringConverter<String>() {
@Override
public String fromString(String string) {
System.out.println("fromString(): before = " + string);

if (string.length() == 14) {
System.out.println("fromString(): after = " + string);

return string;
} else if (string.length() == 10 && string.indexOf('-') == -1) {
String result = String.format("(%s) %s-%s", string.substring(0, 3), string.substring(3, 6),
string.substring(6, 10));
System.out.println("fromString(): after = " + result);

return result;
} else {
return null;
}
}

@Override
public String toString(String object) {

System.out.println("toString(): before = " + object);

if(object == null) {
return "";
}

Pattern p = Pattern.compile("[\\p{Punct}\\p{Blank}]", Pattern.UNICODE_CHARACTER_CLASS);
Matcher m = p.matcher(object);
object = m.replaceAll("");

System.out.println("toString(): after = " + object);

return object;
}
};

我绑定(bind)到 TextField像这样我认为会起作用:
 txtPhone.setTextFormatter(new TextFormatter<String>(formatter, null, filter));
t2.textProperty().bindBidirectional(foo.fooPropertyProperty(), formatter); //I was just testing to see the results in another textfield to see if it would work.

所以我很茫然。我本质上只想允许数字,然后当用户离开该字段时,以格式化的方式显示该值 - 而无需实际更改进入数据库的字符串值。

最佳答案

您在转换器中混淆了 toString()fromString() 方法的用途。 toString() 将文本编辑器的 value 属性转换为显示的文本,而不是相反。尝试在这些方法中切换代码,它应该可以工作。

失去焦点后您的文本字段不显示任何内容的原因是因为调用了 fromString() 方法并返回 null(来自 else 子句)。这会将 null 提交到编辑器的 value 属性。 value 属性的更改通过调用 toString(null) 来更新显示的文本 (textProperty),它将编辑器的 text 属性更改为空字符串。

编辑

下面是我的测试代码,是评论中讨论的后续。我重用了大量您的原始代码。我创建了一个 FXML JavaFX 项目并在 FXML 文件中定义了 TextFieldLabelTextField 接受用户的输入并对其进行格式化。 Label 显示应该进入数据库的文本格式化程序的值(只有数字)。该值可通过调用 formatter.valueProperty().get() 访问。我希望它有所帮助。

import java.net.URL;
import java.util.ResourceBundle;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.util.StringConverter;

public class FXMLDocumentController implements Initializable {

// label displays phone number containing only digits (for database)
@FXML private Label label;

/* field displays formatted text (XXX)-XXX-XXXX after user types
10 digits and presses Enter or if the field looses focus */
@FXML private TextField field;

@Override
public void initialize(URL url, ResourceBundle rb) {

UnaryOperator<TextFormatter.Change> filter = new UnaryOperator<TextFormatter.Change>() {
@Override
public TextFormatter.Change apply(TextFormatter.Change change) {
if (!change.isContentChange()) {
/* nothing is added or deleted but change must be returned
* as it contains selection info and caret position
*/
return change;
}

int maxlength = 14;
if (change.getControlText().indexOf('(') == -1) {
maxlength = 10;
}

if (change.getControlNewText().length() > maxlength
|| change.getText().matches("\\D+")) {
// invalid input. Cancel the change
return null;
}
return change;
}
};

StringConverter<String> converter = new StringConverter<String>() {

// updates displayed text from commited value
@Override
public String toString(String commitedText) {
if (commitedText == null) {
// don't change displayed text
return field.getText();
}

if (commitedText.length() == 10 && !commitedText.matches("\\D+")) {
return String.format("(%s) %s-%s", commitedText.substring(0, 3), commitedText.substring(3, 6),
commitedText.substring(6, 10));
} else {
/* Commited text can be either null or 10 digits.
* Nothing else is allowed by fromString() method unless changed directly
*/
throw new IllegalStateException(
"Unexpected or incomplete phone number value: " + commitedText);
}
}

// commits displayed text to value
@Override
public String fromString(String displayedText) {
// remove formatting characters
Pattern p = Pattern.compile("[\\p{Punct}\\p{Blank}]", Pattern.UNICODE_CHARACTER_CLASS);
Matcher m = p.matcher(displayedText);
displayedText = m.replaceAll("");

if (displayedText.length() != 10) {
// user is not done typing the number. Don't commit
return null;
}

return displayedText;
}
};
TextFormatter<String> formatter = new TextFormatter<String>(converter, "1234567890", filter);
field.setTextFormatter(formatter);
label.textProperty().bind(formatter.valueProperty());
}
}

关于javafx-8 - 如何在 TextField 中格式化字符串而不用 JavaFX 更改它的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37751922/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com