当前位置: 首页 > 知识库问答 >
问题:

在JavaFX中处理键盘输入的优雅方式

景昊焜
2023-03-14

我目前正在开发JavaFX中的计算器,现在正在尝试实现键盘输入支持。

为此,我试图在主. java文件中实现一个EventHandler,如下所示:

@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:

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中单击相应按钮时相同的事情。

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

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

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

共有1个答案

燕刚捷
2023-03-14

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

@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;
    }
}

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

@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 ;

            }
        }
    }
    );
}

等等

 类似资料:
  • 我的代码是: 在上面的代码中,mBooleanLoginDone是一个布尔变量,指示用户是否登录。我希望快捷键Ctrl和T仅在用户成功登录时起作用,但现在我还没有登录,快捷键也起作用。我怎样才能解决它?有什么想法吗?

  • 问题内容: 我想控制Javafx TextField中的输入,以便只允许数字输入,这样,如果超出了最大字符数,则不会对文本框进行任何更改。 编辑:根据评论中的建议,我使用了JavaFX项目负责人建议的方法。阻止输入字母非常有用。我只需要它也可以过滤特殊字符。我尝试将过滤器更改为(text.matchs(“ [0-9]”),但不允许输入退格键。 edit2:找出一个特殊字符和长度的过滤器。这是我的最

  • 我理解 在Scala中应该避免使用null Map.get将返回一个Option[B],我可以使用. getOrElse获取值并回退到默认值 例如。 同时,我正在与一个Java库交互,其中一些值为null。 e、 g.地图(“键1”- 在这种情况下,getOrElse将抛出空指针。 我想处理这两个案件,并导致写这样的东西 这很难看。(这是Map[任何],我需要该键的字符串) 是否可以使用隐式或任何

  • 我希望javafx标签自动更新为正在输入到文本字段中的内容,目前我只有在单击回车键时才更改它。我正在使用秋千和javafx的混合。 这可能吗? 谢谢

  • 8.3.1 键盘输入的中断功能 键盘输入是绝大多数程序的主要输入方式,学习和掌握有关键盘输入中断的使用方法对编写交互式程序是非常重要的,也能更进一步理解计算机是如何接受键盘输入的。 1、键盘缓冲区 键盘缓冲区是一个先进先出的环形队列,其所占内存区域如下: KBHead DW ? ;其内存地址为0000:041AH,缓冲区头指针 KBTail DW ? ;其内存地址为0000:041CH,缓冲区尾指

  • 本文向大家介绍Nodejs异步回调的优雅处理方法,包括了Nodejs异步回调的优雅处理方法的使用技巧和注意事项,需要的朋友参考一下 前言 Nodejs最大的亮点就在于事件驱动, 非阻塞I/O 模型,这使得Nodejs具有很强的并发处理能力,非常适合编写网络应用。在Nodejs中大部分的I/O操作几乎都是异步的,也就是我们处理I/O的操作结果基本上都需要在回调函数中处理,比如下面的这个读取文件内容的