设计题目
设计一个简单的计算器,实现如下功能:
(1)用户在窗口(WindowOperation类负责创建)中的两个文本框中输入参与运算的两个操作数。
(2)用户在下拉列选择运算符触发ItemEvent事件,ItemEvent事件的监视器operator(OperatorListener类负责创建)获得运算符,并将运算符传递给ActionEvent事件的监视器computer
(3)用户单击按钮触发ActionEvent事件,监视器computer(ComputerrListener类负责创建)给出运算结果。实现基本的加减乘除运算并且保留得到计算记录,页面整洁好看,实现简单的计算器功能。
类的设计思想
CalculatorApp 类主要用于创建一个简单的图形界面计算器应用程序。它集成了用户输入、操作选择、计算操作以及结果显示等功能,通过图形用户界面(GUI)与用户进行交互,实现基本的数学运算功能。
- 用户友好的界面:创建一个简单易用的计算器界面,通过不同颜色的标签和按钮增强视觉效果,提高用户体验。
- 多种运算功能:支持基本的算术运算(加、减、乘、除、取余、幂运算)以及对数、三角函数等运算,满足用户不同的计算需求。
- 实时结果反馈:在结果显示区域实时显示计算过程和结果,让用户清楚地看到每一步的计算。
- 错误处理:对输入错误(如格式错误、除数为零等)进行适当的错误提示,提高程序的稳定性。
1.成员变量设计思想
- num1Field:用于用户输入第一个数字的文本框。通过创建 JTextField 实例,并设置合适的宽度(这里设置为可容纳 5 个字符),以便用户能够方便地输入数字。
- opComboBox:操作符下拉框,是一个 JComboBox 类型的变量。它包含了一系列预定义的操作符,如 +、-、*、/、%、^、log、sin、cos、tan 等。用户可以通过下拉菜单选择想要执行的数学运算操作符。
- num2Field:与 num1Field 类似,用于用户输入第二个数字的文本框,同样设置为可容纳 5 个字符宽度。
- calcButton:计算按钮,是一个 JButton 类型的变量。设置其背景色为绿色以突出显示,并且为其添加了动作监听器,当用户点击该按钮时,会触发相应的计算操作。
- resultArea:结果显示区域,是一个 JTextArea 类型的变量。设置为不可编辑状态,以防止用户直接修改结果内容,同时设置了特定的背景色来区分显示区域与其他组件。并且将其放置在 JScrollPane 中,以便在结果内容较多时能够滚动查看。
2.构造函数设计思想
- 在构造函数 CalculatorApp() 中,首先进行了窗口的基本设置:
- 设置窗口标题为 “简单计算器”,明确了应用程序的功能。
- 设置窗口大小为 600x350 像素,提供了一个相对合适的界面尺寸,便于用户操作和查看。
- 设置窗口关闭操作,当关闭窗口时退出程序,符合一般应用程序的使用习惯。
- 接着,通过创建和布局各个面板及组件来构建图形界面:
- 创建主面板 mainPanel,并设置其布局为垂直盒布局(BoxLayout.Y_AXIS),以便将输入行面板和结果显示区域等组件按照垂直方向依次排列。
- 创建输入行面板 inputRowPanel,设置其布局为流式布局(FlowLayout),用于容纳输入数字的标签、文本框、操作符标签、下拉框以及计算按钮等组件,并按照从左到右的顺序依次添加这些组件。
- 创建各个标签(如 num1Label、opLabel、num2Label),设置其前景色为蓝色,以便突出显示标签文本,引导用户进行正确的输入操作。
- 创建结果显示区域 resultArea,设置其不可编辑并指定背景色,然后将其放入滚动面板 JScrollPane 中,方便用户查看较长的结果内容。
- 最后,将输入行面板和滚动面板添加到主面板,再将主面板添加到窗口,并设置窗口居中显示,以提供更好的用户体验。
3.actionPerformed 方法设计思想该方法是实现 ActionListener 接口必须重写的方法,用于处理按钮点击等动作事件。当检测到动作事件的源是计算按钮 calcButton 时,执行以下操作:
- 首先尝试从第一个输入框 num1Field 获取用户输入的数字,并将其转换为双精度浮点数类型。
- 对于第二个数字的获取,根据所选操作符进行判断:如果所选操作符不是三角函数(sin、cos、tan)或对数(log),则从第二个输入框 num2Field 获取数字并转换为双精度浮点数类型。
- 根据所选操作符执行相应的数学运算:
- 对于加法、减法、乘法、幂运算等操作,直接按照对应的数学运算规则进行计算,并生成相应的运算过程描述,记录了输入数字、操作符以及计算结果等信息。
- 对于除法和取模运算,在进行计算前先判断除数是否为零,如果除数不为零则进行正常计算并生成过程描述;如果除数为零,则在结果显示区域显示相应的错误提示信息。
- 对于对数运算,先判断输入的底数和真数是否都大于零,如果满足条件则按照对数运算规则进行计算并生成过程描述;否则,显示无效输入的错误提示信息。
- 对于三角函数运算,直接根据输入的角度(以弧度为单位,这里假设用户输入的是弧度值)进行相应三角函数的计算,并生成过程描述。
- 最后,将计算结果和运算过程描述添加到结果显示区域 resultArea 中,以便用户查看计算过程和结果。如果在获取数字过程中出现输入格式错误(通过捕获 NumberFormatException),则在结果显示区域显示 “Invalid input.” 的错误提示信息。
4.main 方法设计思想
- 在 main 方法中,使用 SwingUtilities.invokeLater() 方法来确保在事件调度线程(EDT)中创建和显示图形界面组件。这是因为 Swing 组件必须在 EDT 中进行创建和操作,以避免出现线程相关的问题。
- 在 invokeLater() 方法内部,创建了 CalculatorApp 类的一个实例,并设置其可见,从而启动了整个计算器应用程序,使得用户可以通过图形界面进行数学运算操作。
设计原理
1.界面布局:
- 使用JFrame作为主窗口,设置标题、大小和关闭操作。
- 采用BoxLayout和FlowLayout布局管理器来组织界面组件,将界面分为输入行和结果显示区域两部分。
- 在输入行中,使用标签和文本框来接收用户输入的数字,使用下拉框选择操作符,使用按钮触发计算。
- 在结果显示区域,使用不可编辑的文本区域来显示计算结果和过程描述,并将其放入滚动面板中以便查看更多内容。
2.事件处理:
- 为计算按钮添加动作监听器,当用户点击按钮时,触发计算操作。
- 在动作监听器中,首先尝试将用户输入的数字转换为double类型,如果转换成功,根据选择的操作符进行相应的计算。
- 对于不同的操作符,使用switch语句进行分支处理,计算结果并生成过程描述。
- 如果输入格式错误或出现除数为零等异常情况,结果显示区域显示错误提示信息。
设计代码——CalculatorApp.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
public class CalculatorApp extends JFrame implements ActionListener {
// 第一个数字输入框
private JTextField num1Field;
// 操作符下拉框
private JComboBox<String> opComboBox;
// 第二个数字输入框
private JTextField num2Field;
// 计算按钮
private JButton calcButton;
// 结果显示区域
private JTextArea resultArea;
public CalculatorApp() {
// 设置窗口标题为“简单计算器”
setTitle("简单计算器");
// 设置窗口大小为 600x350 像素
setSize(600, 350);
// 设置窗口关闭操作,关闭窗口时退出程序
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建主面板
JPanel mainPanel = new JPanel();
// 设置主面板布局为垂直盒布局
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
// 创建输入行面板
JPanel inputRowPanel = new JPanel();
// 设置输入行面板布局为流式布局
inputRowPanel.setLayout(new FlowLayout());
// 创建第一个数字的标签,设置前景色为蓝色
JLabel num1Label = new JLabel("第一个数字:");
num1Label.setForeground(Color.BLUE);
// 创建第一个数字输入框
num1Field = new JTextField(5);
// 创建操作符标签,设置前景色为蓝色
JLabel opLabel = new JLabel("运算符:");
opLabel.setForeground(Color.BLUE);
// 创建包含各种操作符的下拉框
String[] operations = {"+", "-", "*", "/", "%", "^", "log", "sin", "cos", "tan"};
opComboBox = new JComboBox<>(operations);
// 创建第二个数字的标签,设置前景色为蓝色
JLabel num2Label = new JLabel("第二个数字:");
num2Label.setForeground(Color.BLUE);
// 创建第二个数字输入框
num2Field = new JTextField(5);
// 创建计算按钮,设置背景色为绿色,并添加动作监听器
calcButton = new JButton("计算");
calcButton.setBackground(Color.GREEN);
calcButton.addActionListener(this);
// 将各个组件添加到输入行面板
inputRowPanel.add(num1Label);
inputRowPanel.add(num1Field);
inputRowPanel.add(opLabel);
inputRowPanel.add(opComboBox);
inputRowPanel.add(num2Label);
inputRowPanel.add(num2Field);
inputRowPanel.add(calcButton);
// 创建结果显示区域,设置不可编辑,并设置背景色
resultArea = new JTextArea(15, 38);
resultArea.setEditable(false);
resultArea.setBackground(Color.getHSBColor(0.6f, 0.8f, 0.8f));
// 将结果显示区域放入滚动面板
JScrollPane scrollPane = new JScrollPane(resultArea);
// 将输入行面板和滚动面板添加到主面板
mainPanel.add(inputRowPanel);
mainPanel.add(scrollPane);
// 将主面板添加到窗口
add(mainPanel);
// 设置窗口居中显示
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int centerX = (screenSize.width - getWidth()) / 2;
int centerY = (screenSize.height - getHeight()) / 2;
setLocation(centerX, centerY);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == calcButton) {
try {
// 从第一个输入框获取数字
double num1 = Double.parseDouble(num1Field.getText());
double num2 = 0;
// 如果操作符不是三角函数或对数,从第二个输入框获取数字
if (!((String) opComboBox.getSelectedItem()).equals("sin") &&
!((String) opComboBox.getSelectedItem()).equals("cos") &&
!((String) opComboBox.getSelectedItem()).equals("tan")) {
num2 = Double.parseDouble(num2Field.getText());
}
double result = 0;
String operation = (String) opComboBox.getSelectedItem();
String processDescription = "";
switch (operation) {
case "+":
result = num1 + num2;
processDescription = String.valueOf(num1) + " + " + String.valueOf(num2) + " = " + result;
break;
case "-":
result = num1 - num2;
processDescription = String.valueOf(num1) + " - " + String.valueOf(num2) + " = " + result;
break;
case "*":
result = num1 * num2;
processDescription = String.valueOf(num1) + " * " + String.valueOf(num2) + " = " + result;
break;
case "/":
if (num2!= 0) {
result = num1 / num2;
processDescription = String.valueOf(num1) + " / " + String.valueOf(num2) + " = " + result;
} else {
processDescription = "Division by zero is not allowed.";
}
break;
case "%":
if (num2!= 0) {
result = num1 % num2;
processDescription = String.valueOf(num1) + " % " + String.valueOf(num2) + " = " + result;
} else {
processDescription = "Modulo by zero is not allowed.";
}
break;
case "^":
result = Math.pow(num1, num2);
processDescription = String.valueOf(num1) + " ^ " + String.valueOf(num2) + " = " + result;
break;
case "log":
if (num1 > 0 && num2 > 0) {
result = Math.log(num2) / Math.log(num1);
processDescription = "log(" + String.valueOf(num2) + ") base " + String.valueOf(num1) + " = " + result;
} else {
processDescription = "Invalid input for logarithm.";
}
break;
case "sin":
result = Math.sin(num1);
processDescription = "sin(" + String.valueOf(num1) + ") = " + result;
break;
case "cos":
result = Math.cos(num1);
processDescription = "cos(" + String.valueOf(num1) + ") = " + result;
break;
case "tan":
result = Math.tan(num1);
processDescription = "tan(" + String.valueOf(num1) + ") = " + result;
break;
}
// 将计算结果和过程描述添加到结果显示区域
resultArea.setText(resultArea.getText().trim() + "\n" + processDescription);
} catch (NumberFormatException ex) {
// 如果输入格式错误,在结果显示区域显示错误信息
resultArea.setText(resultArea.getText().trim() + "\nInvalid input.");
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
// 创建计算器实例并设置可见
CalculatorApp calculator = new CalculatorApp();
calculator.setVisible(true);
});
}
}