JavaFX如何计算键入错误
我正试图让我的第一个应用程序遇到障碍。该应用程序基本上只是一个简单的打字练习应用程序,用户可以得到一个他们复制的字符串。我正在尝试实现一个计数,它统计用户所犯错误的数量 目前,我有一个代码,它使用一个监听器来观察用户输入到文本区域的字符串。每次用户字符串不等于提供的字符串时,我都会添加一个错误计数,问题是我只想为每个错误的计数添加1。例如,当前,如果您犯了一个错误并键入了2个错误的字符,那么错误计数将上升到3,因为每次按下一个键时代码都会运行,这意味着它会对2个错误字符和1个退格进行计数以删除它们,我希望这只会将1添加到错误计数中 我目前拥有的代码如下:JavaFX如何计算键入错误,java,javafx,Java,Javafx,我正试图让我的第一个应用程序遇到障碍。该应用程序基本上只是一个简单的打字练习应用程序,用户可以得到一个他们复制的字符串。我正在尝试实现一个计数,它统计用户所犯错误的数量 目前,我有一个代码,它使用一个监听器来观察用户输入到文本区域的字符串。每次用户字符串不等于提供的字符串时,我都会添加一个错误计数,问题是我只想为每个错误的计数添加1。例如,当前,如果您犯了一个错误并键入了2个错误的字符,那么错误计数将上升到3,因为每次按下一个键时代码都会运行,这意味着它会对2个错误字符和1个退格进行计数以删除它
public class MainController implements Initializable {
@FXML
private BorderPane errorStatus;
@FXML
private TextArea inputTextArea;
@FXML
public TextArea generatedText;
private String userText;
private String thePassage;
private Integer errorCount = 0;
private Boolean errorCheck = false;
timer time = new timer();
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
thePassage = PassageData.getPassage();
generatedText.setText(thePassage);
inputTextArea.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
if (!inputTextArea.getText().isEmpty()) {
time.start();
}
userText = newValue;
if (userText.equals("") || userText.equals(null)) {
errorStatus.setStyle(
"-fx-background-color: radial-gradient(radius 100%, white, white); -fx-background-radius: 10; -fx-border-radius: 10");
} else if (thePassage.regionMatches(0, userText, 0, userText.length())) {
errorCheck = false;
errorStatus.setStyle(
"-fx-background-color: radial-gradient(radius 100%, green, white); -fx-background-radius: 10; -fx-border-radius: 10");
} else {
errorCheck = true;
errorStatus.setStyle(
"-fx-background-color: radial-gradient(radius 100%, red, white); -fx-background-radius: 10; -fx-border-radius: 10");
}
if (userText.equals(thePassage)) {
thePassage = PassageData.getPassage();
generatedText.setText(thePassage);
Platform.runLater(() -> {
inputTextArea.clear();
});
errorStatus.setStyle(
"-fx-background-color: radial-gradient(radius 100%, white, white); -fx-background-radius: 10; -fx-border-radius: 10");
time.pause();
}
if (errorCheck) {
errorCount++;
System.out.println("Error count = " + errorCount);
}
}
});
}
}您需要为TextArea设置一个更改侦听器,然后将输入字符串的每个字符与输入文本的每个字符进行比较 下面的MCVE演示了这一点:
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
IntegerProperty errorCount = new SimpleIntegerProperty(0);
String target = "This is the sample text to be typed correctly.";
Label instructions = new Label(target);
TextArea textArea = new TextArea();
textArea.setWrapText(true);
HBox hbox = new HBox(5);
hbox.setAlignment(Pos.CENTER);
Label errorsLabel = new Label();
hbox.getChildren().addAll(new Label("Errors:"), errorsLabel);
// Bind the label to errorcount
errorsLabel.textProperty().bind(errorCount.asString());
// Listen for changes to the textArea text and check again target string
textArea.textProperty().addListener((observableValue, s, newValue) -> {
if (newValue != null) {
errorCount.set(getErrorCount(target, newValue));
}
});
root.getChildren().addAll(instructions, textArea, hbox);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private int getErrorCount(String target, String entered) {
int errors = 0;
// Compare each character in the strings
char[] targetChars = target.toCharArray();
char[] enteredChars = entered.toCharArray();
// Starting at the beginning of the entered text, check that each character, in order, matches the target String
for (int i = 0; i < enteredChars.length; i++) {
if (enteredChars[i] != targetChars[i]) {
errors++;
}
}
return errors;
}
}
因此,每次在TextArea中键入或删除字符时,getErrorCount方法都会将输入的文本与目标字符串进行比较。如果任何字符不正确,将增加错误计数
这与上面评论中的提交按钮非常相似,但每次文本区域中的文本更改时都会执行此操作,而不需要额外的按钮。您需要为文本区域设置一个更改侦听器,然后将输入字符串的每个字符与输入文本的每个字符进行比较 下面的MCVE演示了这一点:
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
IntegerProperty errorCount = new SimpleIntegerProperty(0);
String target = "This is the sample text to be typed correctly.";
Label instructions = new Label(target);
TextArea textArea = new TextArea();
textArea.setWrapText(true);
HBox hbox = new HBox(5);
hbox.setAlignment(Pos.CENTER);
Label errorsLabel = new Label();
hbox.getChildren().addAll(new Label("Errors:"), errorsLabel);
// Bind the label to errorcount
errorsLabel.textProperty().bind(errorCount.asString());
// Listen for changes to the textArea text and check again target string
textArea.textProperty().addListener((observableValue, s, newValue) -> {
if (newValue != null) {
errorCount.set(getErrorCount(target, newValue));
}
});
root.getChildren().addAll(instructions, textArea, hbox);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private int getErrorCount(String target, String entered) {
int errors = 0;
// Compare each character in the strings
char[] targetChars = target.toCharArray();
char[] enteredChars = entered.toCharArray();
// Starting at the beginning of the entered text, check that each character, in order, matches the target String
for (int i = 0; i < enteredChars.length; i++) {
if (enteredChars[i] != targetChars[i]) {
errors++;
}
}
return errors;
}
}
因此,每次在TextArea中键入或删除字符时,getErrorCount方法都会将输入的文本与目标字符串进行比较。如果任何字符不正确,将增加错误计数
这与上面评论中的Submit按钮想法非常相似,但每次文本区域中的文本更改时都会执行,而不需要额外的按钮。如果框架提供更高级别的支持,重复几个问题时不要使用低级侦听器 在此上下文中,对文本输入的细粒度更改的高级别支持是一个重要的特性,特别是它的过滤器属性。当文本以任何方式(包括插入符号导航)更改时,都会通知这样的过滤器,甚至允许修改更改-所有这些都是在textProperty更改之前进行的 将根据给定文本计算错误的原始代码段-有关上下文,请参阅
如果框架提供了更高级别的支持,那么重复几个问题不要使用低级侦听器 在此上下文中,对文本输入的细粒度更改的高级别支持是一个重要的特性,特别是它的过滤器属性。当文本以任何方式(包括插入符号导航)更改时,都会通知这样的过滤器,甚至允许修改更改-所有这些都是在textProperty更改之前进行的 将根据给定文本计算错误的原始代码段-有关上下文,请参阅
您刚刚发现了几乎没有应用程序在用户输入时执行验证的原因。等待用户输入完毕后再进行验证。最明显的方法是有一个按钮,上面有“提交”或类似的文本。另一个不太明显的方法是设置文本字段的,因此只有当用户按Enter键时才进行验证。我考虑过这样做,但如果我正确理解了这一点,我想在用户出现错误时警告用户,以便他们可以在键入时进行更正。如果我使用了submit之类的按钮,那么我将无法执行此操作,或者我遗漏了什么?我基本上是在尝试制作与工作原理非常相似的东西。使用TextFormatter:在其筛选器中,您可以执行任何您想要的操作,f.i.计算新输入中的错误并忽略清理中的更改effort@VGR可能存在而且实际上存在这样的上下文,即提交验证是正确的操作,但也存在我们希望键入验证的上下文。。。在fx中,使用TextFormatter很容易做到这一点:我们可以选择是直接干预并拒绝更改,还是只添加一些错误标记,或者做我们需要做的任何事情:您刚刚发现了几乎没有应用程序在用户输入时执行验证的原因。等待用户输入完毕后再进行验证。最明显的方法是有一个按钮,上面有“提交”或类似的文本。另一个不太明显的方法是设置文本字段的,因此只有当用户按Enter键时才进行验证。我考虑过这样做,但如果我正确理解了这一点,我想在用户出现错误时警告用户,以便他们可以在键入时进行更正。如果我使用了一个按钮,比如submit,那么我就不能这样做,或者我遗漏了什么?我基本上是想做一些与h非常相似的东西
使用TextFormatter:在它的过滤器中,你可以做任何你想做的事情,f.i.计算新输入中的错误并忽略清理中的更改effort@VGR可能存在而且实际上存在这样的上下文,即提交验证是正确的操作,但也存在我们希望键入验证的上下文。。。在fx中,使用TextFormatter很容易做到这一点:我们可以选择是直接干预并拒绝更改,还是只添加一些错误标记,或者做我们需要做的任何事情:感谢mcve:尽管您的方法不太理想:始终使用可用的最高抽象,这里有一个TextFormatter谢谢你的mcve:虽然你的方法不太理想:总是追求可用的最高抽象,这里有一个TextFormatter谢谢你,这几乎正是我想要的。现在唯一的问题是,当用户开始出错时,我只希望它在错误中添加1。假设他们在一行中输入了3个错误字符,那么错误计数中只会添加1个字符。你对怎么做有什么建议吗?这是很简单的逻辑。。。你所需要的只是一点机会的记录和计数。。。留给你谢谢,这几乎正是我想要的。现在唯一的问题是,当用户开始出错时,我只希望它在错误中添加1。假设他们在一行中输入了3个错误字符,那么错误计数中只会添加1个字符。你对怎么做有什么建议吗?这是很简单的逻辑。。。你所需要的只是一点机会的记录和计数。。。留给你