JavaFX如何计算输入错误

时间:2018-08-07 16:42:04

标签: java javafx

我正在尝试使我的第一个应用程序遇到障碍。该应用程序基本上只是一个简单的打字练习应用程序,在该应用程序中,为用户提供了他们要复制的字符串。我正在尝试实现对用户所犯错误数量进行计数的计数。

当前,我有使用侦听器观察用户输入到文本区域的字符串的代码。我有一个错误计数,每次用户字符串不等于提供的字符串时,都会添加一个错误计数,这是我只想对每个错误将1加到计数中。例如,当前如果您输入错误并键入2个错误的字符,则每次按下一个键时代码运行时,错误计数将上升为3,这意味着它将计算2个错误的字符和1个退格键来删除它们,我想这样做只将错误计数加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);
            }
        }
    });
}

}

2 个答案:

答案 0 :(得分:4)

重复(跨多个问题),如果框架提供更高级别的支持,请不要使用低级别的侦听器!

在这种情况下,TextFormatter是对文本输入进行细粒度更改的高级支持,尤其是其过滤器属性。每当文本以任何方式更改(包括插入符号导航)时,此类过滤器都会收到通知,甚至允许修改更改-在textProperty更改之前的所有

原始代码段,它将针对给定的文本计算错误-有关上下文,请参见the Zephyr's answer

UnaryOperator<TextFormatter.Change> filter = c -> {
    if (c.isAdded()) {
        // tbd: guard against off-range
        int pos = c.getRangeStart();
        if (!c.getText().equals(target.substring(pos, pos + 1))) {
            errorCount.set(errorCount.get() +1);
        }
    }
    return c;
};

textArea.setTextFormatter(new TextFormatter<>(filter));

答案 1 :(得分:0)

您将要为TextArea设置一个更改侦听器,然后将输入String的每个字符与输入文本的每个字符进行比较。

下面的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()方法会将输入的文本与target字符串进行比较。如果任何字符不正确,则会增加错误计数。

这与上面的注释中的“提交”按钮概念很相似,但是每次TextArea中的文本更改时都执行该操作,不需要额外的按钮。