在JavaFX中处理键盘输入的优雅方式 [英] Elegant way to handle Keyboard Input in JavaFX

查看:205
本文介绍了在JavaFX中处理键盘输入的优雅方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在研究JavaFX中的计算器,现在正试图实现键盘输入支持。

I am currently working on a calculator in JavaFX and right now trying to implement keyboard input support.

为此,我试图在main中实现一个EventHandler。像这样的java文件:

For this I am trying to implement an EventHandler in the main .java file like this:

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

    Scene scene_main = new Scene(root);

    stage.setScene(scene_main);
    stage.show();

    scene_main.setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent keyEvent) {

            switch (keyEvent.getCode()) {
                case ENTER:
                    System.out.println("Enter");
                    break;
                case ADD:
                    System.out.println("Plus");
                    break;
                case SUBTRACT:
                    System.out.println("Minus");
                    break;
                case DIVIDE:
                    System.out.println("Division");
                    break;
                case MULTIPLY:
                    System.out.println("Multiply");
                    break;

            }
        }
    }
    );
}

FXMLDocumentController.java:

The FXMLDocumentController.java:

import java.net.URL;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.Random;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;

/**
 *
 * @author ilja
 */
public class FXMLDocumentController implements Initializable {

@FXML
private void handleTestAction(ActionEvent event) throws Exception {
    ((Node) (event.getSource())).getScene().getWindow().hide();
    Parent parent = FXMLLoader.load(getClass().getResource("/calculator/CrashPopup.fxml"));
    Stage stage = new Stage();
    Scene scene = new Scene(parent);
    stage.setScene(scene);
    stage.setTitle("Teeeeest");
    stage.show();
}

private enum State {

    EQUALED, FIRST, SECOND, OPERATOR
}

public static String operator = "+";
private double oldValue = 0;
private double newValue = 0;
private double result = 0;
private String oldText, newText;
private String digit;
private boolean equaled = false;
Random r = new Random();
int i1;

private State state = State.EQUALED;

NumberFormat nf = new DecimalFormat("##.###", new DecimalFormatSymbols(Locale.US));

@FXML
private TextField displayField;

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
    displayField.setText("0");
}

@FXML
private void handleDotAction(ActionEvent event) {

    double result;

    oldText = displayField.getText();

    if (!oldText.isEmpty() && !oldText.contains(".")) {
        newText = oldText + ".";
    } else {
        newText = oldText;
    }

    displayField.setText(newText);
    result = Double.parseDouble(newText);

    if (state == State.EQUALED || state == State.FIRST) {
        oldValue = result;
        state = State.FIRST;
    } else {
        newValue = result;
        state = State.SECOND;
    }
}

@FXML
private void handleDigitAction(ActionEvent event) {

    digit = ((Button) event.getSource()).getText();
    if (state == State.FIRST || state == State.SECOND) {
        oldText = displayField.getText();
    } else {
        oldText = "";
    }

    if ("0".equals(oldText) /*|| "0.0".equals(oldText)*/) {
        displayField.setText(digit);
    } else {
        displayField.setText(oldText + digit);
    }

    if (state == State.EQUALED || state == State.FIRST) {
        oldValue = Double.parseDouble(displayField.getText());
        state = State.FIRST;
    } else {
        newValue = Double.parseDouble(displayField.getText());
        state = State.SECOND;
    }
}

@FXML
private void handleOperator(ActionEvent event) {

    if (state == State.EQUALED) {
        operator = ((Button) event.getSource()).getText();
    }

    if (state == State.SECOND) {
        switch (operator) {
            case "+":
                oldValue += newValue;
                break;
            case "-":
                oldValue -= newValue;
                break;
            case "*":
                oldValue *= newValue;
                break;
            case "/":
                oldValue /= newValue;
                break;
            default:
                break;
        }
        result = oldValue;
        newValue = 0;
        displayField.setText(String.valueOf(nf.format(oldValue)));
    }

    operator = ((Button) event.getSource()).getText();
    state = State.OPERATOR;
}

@FXML
private void handleEqualAction(ActionEvent event) throws Exception{

    i1 = r.nextInt(6 - 0) + 0;

    if (i1 == 1) {
        ((Node) (event.getSource())).getScene().getWindow().hide();
        Parent parent = FXMLLoader.load(getClass().getResource("/calculator/CrashPopup.fxml"));
        Stage stage = new Stage();
        Scene scene = new Scene(parent);
        stage.setScene(scene);
        stage.setTitle("Unerwarteter Fehler");
        stage.show();
    }

    switch (operator) {
        case "+":
            oldValue += newValue;
            break;
        case "-":
            oldValue -= newValue;
            break;
        case "*":
            oldValue *= newValue;
            break;
        case "/":
            oldValue /= newValue;
            break;
        default:
            break;
    }
    result = oldValue;
    displayField.setText(String.valueOf(nf.format(oldValue)));

    state = State.EQUALED;

}

@FXML
private void handleClearAction(ActionEvent event) {
    displayField.setText("0");
    oldValue = 0;
    newValue = 0;
    operator = "+";
    state = State.EQUALED;
}

@FXML
private void handleClearEntryAction(ActionEvent event) {
    displayField.setText("0");
    newValue = 0;
    switch (state) {
        case EQUALED:
            displayField.setText(String.valueOf(nf.format(result)));
            break;
        case FIRST:
            oldValue = 0;
            state = State.EQUALED;
            break;
        case SECOND:
        case OPERATOR:
            newValue = 0;
            state = State.OPERATOR;
            break;
        default:
            break;
    }
}

private void handleZeroAction(ActionEvent event) {
    digit = ((Button) event.getSource()).getText();
    oldText = displayField.getText();
    if ("0".equals(oldText) || "0.0".equals(oldText)) {
        newText = oldText;
    } else {
        newText = oldText + digit;
    }
    displayField.setText(newText);
}
}

现在的问题是,每当按下这些键时当我点击GUI中的相应按钮时,会发生同样的事情。

Now the problem is, that whenever those keys are pressed, the same things should happen as when I click the corresponding buttons in the GUI.

所有数字按钮共享一个onAction事件和+, - ,/,*也分享一个,等等。
他们都在FXMLDocumentController.java文件中使用变量。

All digit-buttons share one onAction event and +,-,/,* also share one, etc. They all use variables in the FXMLDocumentController.java file.

所以我不确定处理这个问题的最佳方法是什么。我可以从main.java文件中调用onAction事件,还是应该将方法内容粘贴(这会导致冗余)复制到此文件中并使变量公开/受保护?

So I am not sure what the best way to handle this is. Can I just invoke the onAction events from within the main.java file or should I copy paste (which would cause redundance) the method content into this file and make the variables public/protected?

我尝试从主文件中调用方法但是失败了因为我不明白该方法将获得哪些参数,因为它们需要一个ActionEvent对象。

I tried invoking the methods from within the main file but failed because I don't understand which parameters the method will get, as they require an ActionEvent object.

推荐答案

如果您重构处理程序方法,以便它们只确定它们所代表的值,那么调用另一个方法,例如:

If you refactor the handler methods so they just determine the value they represent, then call another method, e.g.:

@FXML
private void handleDigitAction(ActionEvent event) {

    String digit = ((Button) event.getSource()).getText();
    handleDigit(digit) ;
}

public void handleDigit(String digit) {
    if (state == State.FIRST || state == State.SECOND) {
        oldText = displayField.getText();
    } else {
        oldText = "";
    }

    if ("0".equals(oldText) /*|| "0.0".equals(oldText)*/) {
        displayField.setText(digit);
    } else {
        displayField.setText(oldText + digit);
    }

    if (state == State.EQUALED || state == State.FIRST) {
        oldValue = Double.parseDouble(displayField.getText());
        state = State.FIRST;
    } else {
        newValue = Double.parseDouble(displayField.getText());
        state = State.SECOND;
    }
}

然后你可以根据需要调用新方法:

then you can call the new method as needed:

@Override
public void start(Stage stage) throws Exception {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
    Parent root = loader.load();
    FXMLDocumentController controller = loader.getController();

    Scene scene_main = new Scene(root);

    stage.setScene(scene_main);
    stage.show();

    scene_main.setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent keyEvent) {

            switch (keyEvent.getCode()) {
                case DIGIT1:
                    controller.handleDigit("1");
                    break ;
                case DIGIT2:
                    controller.handleDigit("2");
                    break ;
                case DIGIT3:
                    controller.handleDigit("3");
                    break ;
                case DIGIT4:
                    controller.handleDigit("4");
                    break ;
                case DIGIT5:
                    controller.handleDigit("5");
                    break ;
                case DIGIT6:
                    controller.handleDigit("6");
                    break ;
                case DIGIT7:
                    controller.handleDigit("7");
                    break ;
                case DIGIT8:
                    controller.handleDigit("8");
                    break ;
                case DIGIT9:
                    controller.handleDigit("9");
                    break ;

            }
        }
    }
    );
}

依此类推。

这篇关于在JavaFX中处理键盘输入的优雅方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆