JavaGUI程序的计算器
本程序利用maven进行构建,idea社区版进行编写,开发工具包为jdk11;利用截取字符串送堆栈的方式完成计算,可以进行加减乘除以及开根号运算,但是目前还不能进行负数的运算。
运行结果
main类
package calculator;
import javax.swing.*;
/**
* @author 徐俊日
* @version 1.0
*/
public class main {//程序的入口
static {
try {
// 这里是皮肤包可以随意切换javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.mcwin.McWinLookAndFeel");
// javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.smart.SmartLookAndFeel");
// javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.luna.LunaLookAndFeel");
javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.aluminium.AluminiumLookAndFeel");
// javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.bernstein.BernsteinLookAndFeel");
// javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.hifi.HiFiLookAndFeel");
// javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.aero.AeroLookAndFeel");
// javax.swing.UIManager.setLookAndFeel("com.jtattoo.plaf.mint.MintLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Calculater_GUI calculater_gui = new Calculater_GUI();
calculater_gui.createAndShowGUI();
}
}
Calculater_GUI类
package calculator;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.Date;
/**
* @author 徐俊日
* @version 1.0
*/
public class Calculater_GUI {
StringBuffer r;
JTextField result_txt;
public void createAndShowGUI() {
Date date = new Date();
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT);
// 对计算器整体框架的建立start
JFrame f = new JFrame("计算器");// 窗口
JPanel centerPanel = new JPanel(); // 中间面板
JPanel startPanel = new JPanel();
// 初始化功能键
JButton left = new JButton("(");
//JLabel data=new JLabel(format.format(date),JLabel.CENTER);
//data.setFont(new Font("Times New Roman",Font.BOLD,17));
JButton clear = new JButton("清除");
JButton right = new JButton(")");
String button[] = {"7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", ".", "0", "=", "+", "根号"};
JButton but0 = new JButton(button[0]);
JButton but1 = new JButton(button[1]);
JButton but2 = new JButton(button[2]);
JButton but3 = new JButton(button[3]);//除号
JButton but4 = new JButton(button[4]);
JButton but5 = new JButton(button[5]);
JButton but6 = new JButton(button[6]);
JButton but7 = new JButton(button[7]);//乘号
JButton but8 = new JButton(button[8]);
JButton but9 = new JButton(button[9]);
JButton but10 = new JButton(button[10]);
JButton but11 = new JButton(button[11]);//减号
JButton but12 = new JButton(button[12]);
JButton but13 = new JButton(button[13]);
JButton but14 = new JButton(button[14]);//等于号
JButton but15 = new JButton(button[15]);//加号
JButton but16 = new JButton(button[16]);//根号
// 单行输入文本框
final JTextField txt = new JTextField();
result_txt = new JTextField();
// 使用网格布局方式
centerPanel.setLayout(new GridLayout(5, 4, 12, 16)); // 左右上下间隔
centerPanel.add(left);
centerPanel.add(clear);
centerPanel.add(right);
centerPanel.add(but16);
centerPanel.add(but0);
centerPanel.add(but1);
centerPanel.add(but2);
centerPanel.add(but3);
centerPanel.add(but4);
centerPanel.add(but5);
centerPanel.add(but6);
centerPanel.add(but7);
centerPanel.add(but8);
centerPanel.add(but9);
centerPanel.add(but10);
centerPanel.add(but11);
centerPanel.add(but12);
centerPanel.add(but13);
centerPanel.add(but14);
centerPanel.add(but15);
//修改按钮文本颜色
but3.setForeground(Color.blue);
but7.setForeground(Color.blue);
but11.setForeground(Color.blue);
but15.setForeground(Color.blue);
but16.setForeground(Color.blue);
clear.setForeground(Color.RED);
centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// 设置容器大小
txt.setPreferredSize(new Dimension(465, 40));
// 设置字体,风格和字号
txt.setFont(new Font("宋体", Font.PLAIN, 28));
// 设置容器大小
//默认显示的字符
txt.setText("0");
result_txt.setPreferredSize(new Dimension(465, 40));
// 设置字体,风格和字号
result_txt.setFont(new Font("宋体", Font.PLAIN, 28));
//设置结果文本框为只读状态
result_txt.setEditable(false);
//设置文本框从右往左显示
result_txt.setHorizontalAlignment(JTextField.RIGHT);
//设置等于按钮的样式
Font myfont = new Font("Courier New", Font.BOLD, 22);
but14.setFont(myfont);
but14.setBackground(Color.orange);
f.add(startPanel);
f.add(txt, BorderLayout.NORTH); // 将单行文本框添加到窗口的 北部
f.add(result_txt, BorderLayout.CENTER);//将结果文本框添加到窗口的中间
f.add(centerPanel, BorderLayout.SOUTH); // 将中间面板添加到窗口的南部
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 点X关闭窗口
f.setLocation(500, 300); // 初始化时定位
f.setSize(600, 440);
// 展示JFrame窗口
f.setVisible(true);
f.setResizable(false); // 禁止拖曳改变窗口大小
f.pack(); // 让窗口的大小自适应
// 对计算器整体框架的建立end
// 为按钮事件添加自定义监听器start
r = new StringBuffer();
but0.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("7");
txt.setText(r.toString());
}
});
but1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("8");
txt.setText(r.toString());
}
});
but2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("9");
txt.setText(r.toString());
}
});
but4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("4");
txt.setText(r.toString());
}
});
but5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("5");
txt.setText(r.toString());
}
});
but6.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("6");
txt.setText(r.toString());
}
});
left.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("(");
txt.setText(r.toString());
}
});
right.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append(")");
txt.setText(r.toString());
}
});
but8.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("1");
txt.setText(r.toString());
}
});
but9.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("2");
txt.setText(r.toString());
}
});
but10.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("3");
txt.setText(r.toString());
}
});
but13.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("0");
txt.setText(r.toString());
}
});
but15.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_result();
r.append("+");
txt.setText(r.toString());
}
});
/**
* 对除法按钮进行监听
*/
but3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_result();
r.append("/");
txt.setText(r.toString());
}
});
but7.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_result();
r.append("*");
txt.setText(r.toString());
}
});
but12.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append(".");
txt.setText(r.toString());
}
});
but11.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_result();
r.append("-");
txt.setText(r.toString());
}
});
clear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.delete(0, r.length()); //清空字符串中的内容
txt.setText(r.toString()); //将清空结果显示在文本框中
result_txt.setText(r.toString());//将清空结果显示在结果文本框中
}
});
//=结算结果并显示
but14.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action_result();
}
});
but16.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r.append("sqrt(");
txt.setText(r.toString());
}
});
}
public void action_result() {
String str = r.toString();
double result = Computer.calculate_sqrt(str);
String string = String.valueOf(result);
//将r字符缓冲区清零
//r.delete(0, r.length());
//将结果添加到r字符缓冲
string = "=" + string;
//显示结果
result_txt.setText(string);
}
}
Computer类
package calculator;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author 徐俊日
* @version 1.0
*/
public class Computer {
/**
* calculate函数将带有sqrt()的字符串利用正则表达式进行处理sqrt()里面的式子传入到solution函数进行运算,将运算结果开根号并替换掉原有的sqrt()式子
* 并与其他式子组成新的字符串,然后再将新字符串传入solution函数进行计算,以此类推来完成sqrt()式子的嵌套计算
*
* @param str 从文本框获取的字符串
* @return 计算结果
*/
public static double calculate_sqrt(String str) {
//利用正则表达式来处理sqrt()里的式子
String pattern = "(?<=sqrt\\().+?(?=\\))";
// 创建 Pattern 对象
Pattern r = Pattern.compile(pattern);
// 创建 matcher 对象
Matcher m = r.matcher(str);
// 匹配到数据
while (m.find()) {
// m.group(0) 取到括号内的式子
//将式子传入solution函数进行运算
double result = Computer.solution(m.group(0));
// 将得到的结果用Math.sqrt进行开方
double value = Math.sqrt(result);
// 把原来的sqrt()式子整个替换成计算的结果
str = str.replace("sqrt(" + m.group(0) + ")", String.valueOf(value));
}
//进没有sqrt()式子的新字符串传入solution函数进行最后的结果运算
return Computer.solution(str);
}
public static double solution(String str) {
Stack<Double> numStack = new Stack<>();
Stack<Character> signalStack = new Stack<>();
int index = 0;// 记录已经执行的符号数
int len = str.length();
while (index < len) {
char c = str.charAt(index); // 取出这一步的符号
if (c == '(') {
signalStack.push(c);// 若是左括号就进栈
}
// 否则要先判断优先级
else if (c == '+' || c == '-' || c == '*' || c == '/') {
int currOperLevel = getOperlevel(c);// 当前符号的优先级
while (true) {
int stackOperLevel = 0;// 栈顶元素的优先级
if (!signalStack.isEmpty()) {
Object obj = signalStack.peek();
stackOperLevel = getOperlevel((char) obj);
}
// 若当前元素优先级大于栈顶元素的优先级则入栈
if (currOperLevel > stackOperLevel) {
signalStack.push(c);
break;// 直到让比自己优先级高的符号都出栈运算了再把自己进栈
} else {// 不能入栈就进行计算
try {
char optemp = '0';
double num1 = 0;
double num2 = 0;
if (!signalStack.isEmpty()) {
optemp = (char) signalStack.pop();// 取出优先级大的那个符号
}
if (!numStack.isEmpty()) {
num1 = (double) numStack.pop();
num2 = (double) numStack.pop();// 取出数据栈中的两个数
}
numStack.push(caculateResult(optemp, num2, num1));// 将算出来的结果数据再次进入数据栈
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
} else if (c == ')') {// 右括号就返回栈顶元素,右括号是不进栈的
while (true) {
char theop = (char) signalStack.pop();
if (theop == '(') {
break;
} else {
try {
double num1 = (double) numStack.pop();
double num2 = (double) numStack.pop();
numStack.push(caculateResult(theop, num2, num1));// 运算括号内的内容
} catch (Exception e) {
e.printStackTrace();
}
}
}
} else if (c >= '0' && c <= '9') {
int tempIndex = index + 1;
while (tempIndex < len) {
char temp = str.charAt(tempIndex);// 取字符串中处于当前字符的下一位
if ((temp >= '0' && temp <= '9') || temp == '.') {
tempIndex++;// 若为数字则继续向后取
} else {
break;// 证明数字去完
}
}
String numstr = str.substring(index, tempIndex);// 截取这个字符串则为两个符号之间的数字
try {
double numnum = Double.parseDouble(numstr);// 将数字转换成整型便于运算
numStack.push(numnum);
index = tempIndex - 1;
} catch (Exception e) {
e.printStackTrace();
}
}
index++;
}
// 检查符号栈是否为空
while (true) {
Object obj = null;
if (signalStack.isEmpty() == false) {
obj = signalStack.pop();
}
if (obj == null) {
break;// 为空证明运算已结束
} else {// 不为空就出栈运算
try {//使用异常捕获让只输入了左括号没有输入有括号的程序得以正常运行
char opterTemp = (char) obj;
double num1 = (double) numStack.pop();
double num2 = (double) numStack.pop();
numStack.push(caculateResult(opterTemp, num2, num1));
} catch (Exception e) {
System.out.println(e);
}
}
}
double result = 0;
try {
result = (double) numStack.pop();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return result;
}
//计算加减乘除余
private static Double caculateResult(char optemp, double num1, double num2) {
switch (optemp) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return num1 / num2;
}
return 0.0;
}
//返回符号优先级
private static int getOperlevel(char c) {
switch (c) {
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>JiSuanQi</artifactId>
<version>1.0-SNAPSHOT</version>
<name>JiSuanQi</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.jtattoo/JTattoo -->
<dependency>
<groupId>com.jtattoo</groupId>
<artifactId>JTattoo</artifactId>
<version>1.6.13</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>