最近在学习java ,在学习的过程中想找几个简单的小程序练手。用Java写一个计算器算一个难度非常低的练习,它将我之前学过的 Java 的知识重新地拾起来了。在这个小练习中,我选择了逻辑层和显示层分离(MVC模式)的JavaFX 技术。在javafx 中,用fxml文件来表示显示层内容,用Java 来编写程序的业务逻辑。
|-- 显示层设计
|-- 逻辑层设计
|-- 源代码
显示层的设计中只存在一个简单的界面,界面中包含两部分 -- 按钮区和显示区。具体的界面如图:
具体的布局为 :
SpiltPane--|--VBox--|--HBox
| |--HBox
| |--HBox
|
|--GridPane
在整个JavaFX程序中,显示层的界面和布局都是由fxml 文件生成的,在idea中可以直接由集成的Java Scene Builder 拖拽和配置相应的参数完成。
在这次的练习中计算器的设计逻辑是这样的:
1. 用一个Stack 去存储输入的数字和操作符,并将输入input1,input2分别用两个StringBuffer类存储,并实时更新到显示区域。
2. 每点击一个数字,都会在显示区域的标签中, 并分别存入输入栈和 输入字符串的StringBuffer中。
3. 用操作符来区分输入的数字是第一个还是第二个。
4. 当点击删除(DEL)时,从栈中将栈顶的元素删除,从输入的StringBuffer类中去掉这个字符。当点击Clear 时,清空输入栈(inputStack)和输入字符串(firstInputStr,secondInputStr)。并将对应的结果实时更新到显示区。
5. 当点击 ' = ' 时,开始进行计算,并把计算的结果反馈到显示区域。每次计算之后,都会对相应的参数进行清空。
GitHub仓库:https://github.com/XDKejin/java_files_of_my_study
1. Calculator.java
package calculator;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Calculator extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("calculator.fxml"));
primaryStage.setTitle("Calculator");
primaryStage.setScene(new Scene(root, 400, 500));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
2. CalculatorController.java
package calculator;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.Stack;
public class CalculatorController implements Initializable{
@FXML private Label firstInput;
@FXML private Label secondInput;
@FXML private Label showResult;
@FXML private Label showOperator;
Stack inputStack ;
StringBuffer firstInputStr;
StringBuffer secondInputStr;
char operator;
boolean isChanged = false;
int result; //store result
@Override
public void initialize(URL location, ResourceBundle resources) {
firstInputStr = new StringBuffer();
secondInputStr = new StringBuffer();
inputStack = new Stack();
}
/*
* number button action code is below here:
* */
@FXML protected void pressNumZero(ActionEvent event){
if (!isChanged)
firstInputStr.append('0');
else
secondInputStr.append('0');
inputStack.push('0');
putStrToLabel();
}
@FXML protected void pressNumOne(ActionEvent event){
if (!isChanged)
firstInputStr.append('1');
else
secondInputStr.append('1');
inputStack.push('1');
putStrToLabel();
}
@FXML protected void pressNumTwo(ActionEvent event){
if (!isChanged)
firstInputStr.append('2');
else
secondInputStr.append('2');
inputStack.push('2');
putStrToLabel();
}
@FXML protected void pressNumThree(ActionEvent event){
if (!isChanged)
firstInputStr.append('3');
else
secondInputStr.append('3');
inputStack.push('3');
putStrToLabel();
}
@FXML protected void pressNumFour(ActionEvent event){
if (!isChanged)
firstInputStr.append('4');
else
secondInputStr.append('4');
inputStack.push('4');
putStrToLabel();
}
@FXML protected void pressNumFive(ActionEvent event){
if (!isChanged)
firstInputStr.append('5');
else
secondInputStr.append('5');
inputStack.push('5');
putStrToLabel();
}
@FXML protected void pressNumSix(ActionEvent event){
if (!isChanged)
firstInputStr.append('6');
else
secondInputStr.append('6');
inputStack.push('6');
putStrToLabel();
}
@FXML protected void pressNumSeven(ActionEvent event){
if (!isChanged)
firstInputStr.append('7');
else
secondInputStr.append('7');
inputStack.push('7');
putStrToLabel();
}
@FXML protected void pressNumEight(ActionEvent event){
if (!isChanged)
firstInputStr.append('8');
else
secondInputStr.append('8');
inputStack.push('8');
putStrToLabel();
}
@FXML protected void pressNumNine(ActionEvent event){
if (!isChanged)
firstInputStr.append('9');
else
secondInputStr.append('9');
inputStack.push('9');
putStrToLabel();
}
/*
* operator button action code is below here;
*
* */
@FXML protected void pressOperatorAdd(ActionEvent event){
operator = '+';
inputStack.push('+');
showOperator.setText("+");
isChanged = true;
}
@FXML protected void pressOperatorMinus(ActionEvent event){
operator = '-';
inputStack.push('-');
showOperator.setText("-");
isChanged = true;
}
@FXML protected void pressOperatorMultiply(ActionEvent event){
operator = '*';
inputStack.push('*');
showOperator.setText("*");
isChanged = true;
}
@FXML protected void pressOperatorDivide(ActionEvent event){
operator = '/';
inputStack.push('/');
showOperator.setText("/");
isChanged = true;
}
@FXML protected void pressOperatorMod(ActionEvent event){
operator = '%';
inputStack.push('%');
showOperator.setText("%");
isChanged = true;
}
/*
* function key action code is below here
* */
@FXML protected void pressFunckeyDel(ActionEvent event){
if (inputStack.empty()){
clearCache();
updateDisplay();
return;
}
if ( (int)(inputStack.peek()) >= (int)('0') && (int)(inputStack.peek()) <= (int)('9')){
if (!isChanged)
firstInputStr.deleteCharAt( firstInputStr.length() - 1 );
else
secondInputStr.deleteCharAt( secondInputStr.length() - 1 );
}else {
showOperator.setText("");
isChanged = false;
}
inputStack.pop();
updateDisplay();
}
@FXML protected void pressFunckeyClear(ActionEvent event){
clearCache();
updateDisplay();
}
/*
* press '=' button get RESULT
* */
@FXML protected void getResult(ActionEvent event){
int first = Integer.parseInt(firstInputStr.toString());
int second = Integer.parseInt(secondInputStr.toString());
switch (operator){
case '+' :
result = first + second;
break;
case '-' :
result = first - second;
break;
case '*' :
result = first * second;
break;
case '/' :
if (0 == second)
break;
result = first / second;
break;
case '%' :
result = first % second;
break;
}
showResult.setText(result+"");
//清空各种参数的缓存
clearCache();
}
/*
* extra method
*
* */
void putStrToLabel(){
firstInput.setText(firstInputStr.toString());
secondInput.setText(secondInputStr.toString());
}
void updateDisplay(){
if (inputStack.empty()){
setDisplayNull();
return;
}
firstInput.setText(firstInputStr.toString());
secondInput.setText(secondInputStr.toString());
showOperator.setText(operator+"");
if ( 0 == result )
showResult.setText("");
else
showResult.setText(result+"");
}
void clearCache(){
isChanged = false;
firstInputStr.delete( 0,(firstInputStr.length()) );
secondInputStr.delete( 0, (secondInputStr.length()));
result = 0;
while(!inputStack.empty()){
inputStack.pop();
System.out.println(inputStack.toString());
}
}
void setDisplayNull(){
firstInput.setText("");
secondInput.setText("");
showOperator.setText("");
showResult.setText("");
}
}
3. calculator.fxml