我目前正在研究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对象。
答案 0 :(得分:1)
如果您重构处理程序方法,以便它们只确定它们所代表的值,那么调用另一个方法,例如:
@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 ;
}
}
}
);
}
等等。