第一次作业

发布时间 2023-10-14 20:22:51作者: 木250

一、设计的可实现加、减、乘、除功能的计算器软件:

二、关键代码package counter

package counter;
//引用包
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;
import javax.swing.*;

//处理计算结果异常

class MyException extends Exception{
private static final long serialVersionUID = 1649159247013670200L;
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}


public class SwingConsole {
public static void run(final JFrame f,final int width,final int height){
//调用invokeLater来请求事件分发线程以运行某段代 码
//必须将这段代码放入一个Runnable对象的run方法中,并将该指定Runnable对象作为参数传递给invokeLater。
SwingUtilities.invokeLater(new Runnable(){
//invokeLater函数会立即返回,不会等到事件分发线程执行完这段代码。
public void run(){

f.setTitle(f.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(width,height);
f.setVisible(true);
}
});
}
}



class calculator2 extends JFrame{

private static final long serialVersionUID = 1L;
//定义变量
private JTextField textField; //输入文本框
private String input; //结果
private JButton button; //按钮
private JLabel jlabel;
//在构造方法中重写,创建框架,创建组件,添加组件,以及给组件注册事件监听器

public calculator2() {
//由于在线程设置里设置了title,所以这里不用再设计
super("计算器");
//在屏幕上显示计算器的位置为(500, 300)
this.setLocation(500, 300);
input = "";
//得到框架的内容窗格,才可以添加组件,使用默认的BorderLayout
Container container = this.getContentPane();
//创建中间容器JPanel
JPanel panel = new JPanel();
//设置颜色
this.setBackground(Color.blue);

//创建文本框,指定单行长度
textField = new JTextField(30);

textField.setEditable(false); //文本框禁止编辑
textField.setHorizontalAlignment(JTextField.LEFT);
//textField.setBounds(100, 100, 20, 20); //在容器布局为空情况下生效
textField.setPreferredSize(new Dimension(200,30));
//设置文本框颜色
textField.setBackground(Color.WHITE);
//使用add来添加组件,添加文本框到北部
container.add(textField, BorderLayout.NORTH);
//添加标题
jlabel = new JLabel("DESIGN BY **",JLabel.CENTER);
container.add(jlabel,BorderLayout.SOUTH);
String[] name=
{"1","2","3","+","4","5","6","-","7","8","9","*","0","C","=","/"};
//给中间容器设置布局管理器,GridLayout(4,4,1,1)设置行数,列数,组件水平距离,垂直距离
panel.setLayout(new GridLayout(4,4,1,1));
//将16个按钮放入JPanel
for(int i=0;i<name.length;i++) {

button = new JButton(name[i]);
//给按钮添加事件监听器
button.addActionListener(new MyActionListener());
//添加按钮组件
panel.add(button);
if((i==3)||(i==7)||(i==11)||(i==14)||(i==15))button.setBackground(Color.RED);
if(i==14)button.setBackground(Color.GREEN);
}
//添加JPanel到中部
container.add(panel,BorderLayout.CENTER);
String[] name2= {"%","1/X","sqrt"};
JPanel panel2 = new JPanel();
panel2.setLayout(new GridLayout(3,1,1,1));
//将16个按钮放入JPanel
for(int i=0;i<name2.length;i++) {
button = new JButton(name2[i]);
//给按钮添加事件监听器
button.addActionListener(new MyActionListener());
//添加按钮组件
button.setBackground(Color.RED); panel2.add(button); }
//添加JPanel到中部
container.add(panel2,BorderLayout.EAST);
}
//继承事件适配器,重写事件监听器的方法
//内部类实现按钮响应,将输入值送入
class MyActionListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
int cnt=0;
String actionCommand = e.getActionCommand();
//获取按钮上的字符串
//用equals函数来判断是否为符号,若是括号中的则为true
if(actionCommand.equals("+") || actionCommand.equals("-") ||
actionCommand.equals("*")
|| actionCommand.equals("/")||actionCommand.equals("%"))
{
input += " " + actionCommand + " ";
}
//按下C清除输入
else if(actionCommand.equals("C")) {
input = "";
}
//按下1/x求相反数
else if(actionCommand.equals("1/X")) {
input += " " + actionCommand + " ";
}
//按下sqrt求相反数
else if(actionCommand.equals("sqrt")) { input += " " + actionCommand + " "; }
//按下等号,若有异常,则调用MyException
else if(actionCommand.equals("=")) {
try {
input+= "="+calculate(input);
} catch (MyException e1) {
if(e1.getMessage().equals("Infinity"))
input+= "=" + e1.getMessage();
else
input = e1.getMessage();
}
//文本框输出input
textField.setText(input);
//储存结果清零
input="";
//cnt置1表示计算结束
cnt = 1;
}
else//按下数字
input += actionCommand;

//cnt为零时,输入继续,储存之前的结果
if(cnt == 0)

textField.setText(input);
}
}

//借助栈来完成表达式的计算
private String calculate(String input) throws MyException{
//创建数组
String[] comput = input.split(" ");
//创建栈
Stack<Double> stack = new Stack<>();
//创建变量
Double m = Double.parseDouble(comput[0]);
//第一个操作数入栈
stack.push(m);
//将字符串分割成字符串数组,依次运算
for(int i = 1; i < comput.length; i++) {
//数组奇数位为运算符(从第0位开始),偶数位为操作数,因此可将偶数为操作数进栈,
if(i%2==1) {
//遇见+(-)运算符,则将下一个数以正(负)的形式压人栈中
if(comput[i].equals("+"))
stack.push(Double.parseDouble(comput[i+1]));
if(comput[i].equals("-"))

stack.push(-Double.parseDouble(comput[i+1]));
//遇见*或/运算符,则将栈顶元素出栈与数组后一元素进行计算,并将其结果重新压入栈中,直至遍历至数组最后一个元素。最后将栈中的元素进行求和。
if(comput[i].equals("*")) {
Double d = stack.peek(); //取栈顶元素
stack.pop(); //将栈顶元素出栈
stack.push(d*Double.parseDouble(comput[i+1]));//做乘法再入栈
}

if(comput[i].equals("/")) {
//将前一个数出栈做乘法再入栈
double help = Double.parseDouble(comput[i+1]);
if(help == 0)
throw new MyException("Infinity"); //若0是除数,不会继续执行该函数

double d = stack.peek();
stack.pop();
stack.push(d/help);
}

if(comput[i].equals("%")) {
double help = Double.parseDouble(comput[i+1]);
if(help == 0)
throw new MyException("Infinity"); //若0是除数,不会继续执行该函数
double d = stack.peek(); //取栈顶元素
stack.pop(); //将栈顶元素出栈
stack.push(d%Double.parseDouble(comput[i+1]));//做求余再入栈
}
if(comput[i].equals("sqrt")) {
Double d = stack.peek(); //取栈顶元素
stack.pop(); //将栈顶元素出栈
stack.push(Math.sqrt(d));//做乘法再入栈
}
if(comput[i].equals("1/X")) {
double help = Double.parseDouble(comput[i-1]);
if(help == 0)
throw new MyException("Infinity"); //若0是除数,不会继续执行该函数
else{
double d = stack.peek(); //取栈顶元素
stack.pop(); //将栈顶元素出栈
stack.push(1/d);}//做求余再入栈
}
}
}
//将栈中元素求和
double d = 0;
while(!stack.isEmpty()) {
d += stack.peek();
stack.pop();
}
//强制转换类型为字符,返回结果
String result = String.valueOf(d);
return result;
}
//main方法
public static void main(String[] args) {
//创建计算机,并且设置长宽
SwingConsole.run(new calculator2(), 250, 300);
}

}
三、使用Visio设计计算器软件中所涉及的流程图:

四、软件测试结果: