系列文章目录
提示:阅读本章之前,请先阅读目录
文章目录
- 系列文章目录
- 前言
- 一、常规配置
- 1. 设置窗口大小
- 2. 获取当前屏幕的尺寸
- 3. 窗口居中
- 4. 设置窗口名称
- 5. 添加监听器,关闭窗口
- 6. 设置窗口可见性
- 7. 设置文本框不可编辑
- 8. 设置文本框提示
- 9. 设置文本框的尺寸大小
- 10. 设置文本框的字体样式
- 11. 设置文本域的滚动条
- 12. 弹出框提示
- 13. 警告弹出框提示
- 二、目录结构
- 三、Calculator.java,入口
- 四、MyFrame.java 创建窗口frame
- 五、WindowClose.java,监听关闭
- 六、WindowVisible.java,设置窗口可见性
- 七、SetComponent.java,绘制各种组件
- 八、ButtonListener.java 按键监听器,处理按键事件
- 九、异常处理
- 十、exe4j Wizard 使用生成exe
- 1. 先在 IntelliJ IDEA 安装Handy Export Jar![在这里插入图片描述](https://img-blog.csdnimg.cn/11d4a5d5ba1047db8e869fa7bfb947f5.png)
- 2. 然后导出为jar包
- 3. 打开exe4j Wizard
- 更新日志
前言
通过学习java 的gui编程,可以快速学习java基础语法,让我们来看看如何制作一个简易计算器,以下包含全部源码。
简易计算器 v1.2 图形界面
计算过程的界面
一、常规配置
1. 设置窗口大小
setSize(600, 590);
2. 获取当前屏幕的尺寸
int screenWidth = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
int screenHeight = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
// 最后可用于设置窗口位置
setLocation(screenWidth/3, screenHeight/6);
3. 窗口居中
setLocationRelativeTo(null);
4. 设置窗口名称
setTitle(title);
5. 添加监听器,关闭窗口
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
6. 设置窗口可见性
frame.setVisible(true);
7. 设置文本框不可编辑
jTextField1.setEditable(false);
8. 设置文本框提示
jTextField1.setToolTipText("请输入计算数字");
9. 设置文本框的尺寸大小
jTextField1.setPreferredSize(new Dimension(580, 40));
10. 设置文本框的字体样式
jTextField1.setFont(new Font("", Font.BOLD, 20));
11. 设置文本域的滚动条
JTextArea jTextArea1 = new JTextArea();
JScrollPane sp = new JScrollPane(jTextArea1);
sp.setPreferredSize(new Dimension(580, 160));
p7.add(sp);
12. 弹出框提示
JOptionPane.showMessageDialog(null,"暂时不支持超过10位数字的计算");
13. 警告弹出框提示
JOptionPane.showMessageDialog(null, "系统出现了计算错误", "系统报错 " + "可联系管理员处理", JOptionPane.ERROR_MESSAGE);
二、目录结构
ButtonListener.java 按键监听器,主要进行处理各种按键之后的事件,算法
Calculator.java 入口程序
MyFrame.java 创建一个frame窗口
SetComponent.java 绘制界面,按钮,面板,输入框
WindowClose.java 监听窗口关闭
WindowVisible.java 设置窗口为可见性
三、Calculator.java,入口
package com.tools;
public class Calculator {
public static void main(String[] args) {
// 初始化窗口
MyFrame myFrame = new MyFrame("Smobee Calculator v1.2");
// 初始化组件
new SetComponent(myFrame);
// 设置监听关闭
new WindowClose(myFrame);
// 设置窗口加载完,就显示可见
new WindowVisible(myFrame);
}
}
四、MyFrame.java 创建窗口frame
package com.tools;
import java.awt.*;
public class MyFrame extends Frame {
MyFrame(String title) {
// 设置窗口大小
setSize(600, 590);
// 窗口居中
setLocationRelativeTo(null);
// 设置窗口名称
setTitle(title);
}
}
五、WindowClose.java,监听关闭
package com.tools;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class WindowClose {
WindowClose(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// 监听到点击关闭按钮,关闭程序
System.exit(0);
}
});
}
}
六、WindowVisible.java,设置窗口可见性
要在所有的组件添加完毕之后,再设置窗口可见性,要不然,第一次显示窗口,会是一片空白
package com.tools;
import java.awt.*;
public class WindowVisible {
WindowVisible(Frame frame) {
// 设置frame窗口,为可见
frame.setVisible(true);
}
}
七、SetComponent.java,绘制各种组件
package com.tools;
import javax.swing.*;
import javax.swing.text.Highlighter;
import java.awt.*;
public class SetComponent {
JButton jButton1,jButton2,jButton3,jButton4,jButton5,jButton6,jButton7,jButton8,jButton9,jButton10,jButton11,jButton12,jButton13,jButton14,jButton15,jButton16,jButton17,jButton18,jButton19,jButton20;
JTextField jTextField1;
JTextArea jTextArea1;
// 两个数
double number1, number2;
// 当前第几个数
int selectNumber = 1;
// 是否为小数点
boolean isFloat = false;
// 当前算法 0 无 1 加 2 减 3 乘 4 除 5 除...余
String algo = "no";
// 第一个数字激活状态
boolean number1State = false;
// 第二个数字激活状态
boolean number2State = false;
// 是否计算结束
boolean calcState = false;
SetComponent(Frame frame) {
// 创建整体的面板
Panel panel = new Panel();
// 第一层
Panel p1 = new Panel(new FlowLayout());
jTextField1 = new JTextField();
jTextField1.setEditable(false);
jTextField1.setToolTipText("请输入计算数字");
jTextField1.setPreferredSize(new Dimension(580, 40));
jTextField1.setFont(new Font("", Font.BOLD, 20));
p1.add(jTextField1);
// 第二层
Panel p2 = new Panel(new GridLayout(1, 4));
jButton1 = new JButton("C");
jButton2 = new JButton("÷");
jButton3 = new JButton("*");
jButton4 = new JButton("Del");
jButton1.setPreferredSize(new Dimension(145, 60));
jButton1.addActionListener(new ButtonListener(this));
jButton2.addActionListener(new ButtonListener(this));
jButton3.addActionListener(new ButtonListener(this));
jButton4.addActionListener(new ButtonListener(this));
// 第三层
Panel p3 = new Panel(new GridLayout(1, 4));
jButton5 = new JButton("7");
jButton6 = new JButton("8");
jButton7 = new JButton("9");
jButton8 = new JButton("-");
jButton5.setPreferredSize(new Dimension(145, 60));
jButton5.addActionListener(new ButtonListener(this));
jButton6.addActionListener(new ButtonListener(this));
jButton7.addActionListener(new ButtonListener(this));
jButton8.addActionListener(new ButtonListener(this));
// 第四层
Panel p4 = new Panel(new GridLayout(1, 4));
jButton9 = new JButton("4");
jButton10 = new JButton("5");
jButton11 = new JButton("6");
jButton12 = new JButton("+");
jButton9.setPreferredSize(new Dimension(145, 60));
jButton9.addActionListener(new ButtonListener(this));
jButton10.addActionListener(new ButtonListener(this));
jButton11.addActionListener(new ButtonListener(this));
jButton12.addActionListener(new ButtonListener(this));
// 第五层
Panel p5 = new Panel(new GridLayout(1, 4));
jButton13 = new JButton("1");
jButton14 = new JButton("2");
jButton15 = new JButton("3");
jButton16 = new JButton("√");
jButton13.setPreferredSize(new Dimension(145, 60));
jButton13.addActionListener(new ButtonListener(this));
jButton14.addActionListener(new ButtonListener(this));
jButton15.addActionListener(new ButtonListener(this));
jButton16.addActionListener(new ButtonListener(this));
// 第六层
Panel p6 = new Panel(new GridLayout(1, 4));
jButton17 = new JButton("%");
jButton18 = new JButton("0");
jButton19 = new JButton(".");
jButton20 = new JButton("=");
jButton17.setPreferredSize(new Dimension(145, 60));
jButton17.addActionListener(new ButtonListener(this));
jButton18.addActionListener(new ButtonListener(this));
jButton19.addActionListener(new ButtonListener(this));
jButton20.addActionListener(new ButtonListener(this));
// 第七层
Panel p7 = new Panel(new GridLayout(1, 1));
jTextArea1 = new JTextArea();
JScrollPane sp = new JScrollPane(jTextArea1);
sp.setPreferredSize(new Dimension(580, 160));
jTextArea1.setText("历史计算:");
jTextArea1.setEditable(false);
// 放进容器
panel.add(p1);
p2.add(jButton1);
p2.add(jButton2);
p2.add(jButton3);
p2.add(jButton4);
p3.add(jButton5);
p3.add(jButton6);
p3.add(jButton7);
p3.add(jButton8);
p4.add(jButton9);
p4.add(jButton10);
p4.add(jButton11);
p4.add(jButton12);
p5.add(jButton13);
p5.add(jButton14);
p5.add(jButton15);
p5.add(jButton16);
p6.add(jButton17);
p6.add(jButton18);
p6.add(jButton19);
p6.add(jButton20);
p7.add(sp);
panel.add(p2);
panel.add(p3);
panel.add(p4);
panel.add(p5);
panel.add(p6);
panel.add(p7);
frame.add(panel);
}
}
八、ButtonListener.java 按键监听器,处理按键事件
这里主要进行各种算法的运算,其中,就用到比较简单的方法,没有用Math进行算法,主要是为了练习,如果您追求细节,可以尝试修改代码,使其更加符合标准计算器的算法
本程序,还尚有许多bug,主要是时间不够,各位同学如发现有计算bug,可以提交到评论区或私信,同学们也可以发挥个人能力
package com.tools;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
public class ButtonListener implements ActionListener {
SetComponent setComponent;
ButtonListener(SetComponent setComponent) {
this.setComponent = setComponent;
}
private void setText(Double result) {
if (this.setComponent.isFloat || this.setComponent.algo.equals("÷")) {
DecimalFormat df = new DecimalFormat("0.00");
this.setComponent.jTextField1.setText(Double.toString(Double.parseDouble(df.format(result))));
} else {
int x = (int) Math.round(result);
this.setComponent.jTextField1.setText(Integer.toString(x));
}
}
private void clearNunber(Boolean clearText, Boolean clearCalc) {
if (clearText) {
this.setComponent.jTextField1.setText("");
}
if (clearCalc) {
this.setComponent.calcState = false;
}
this.setComponent.selectNumber = 1;
this.setComponent.number1 = 0;
this.setComponent.number2 = 0;
this.setComponent.number1State = false;
this.setComponent.number2State = false;
this.setComponent.isFloat = false;
this.setComponent.algo = "no";
}
private void calcNumber() {
double result = 0;
// 判断两个数,是否都输入了
if (this.setComponent.number1State && this.setComponent.number2State) {
String algo = this.setComponent.algo;
if (algo.equals("*")) {
result = this.setComponent.number1 * this.setComponent.number2;
} else if (algo.equals("÷")) {
result = this.setComponent.number1 / this.setComponent.number2;
} else if (algo.equals("-")) {
result = this.setComponent.number1 - this.setComponent.number2;
} else if (algo.equals("+")) {
result = this.setComponent.number1 + this.setComponent.number2;
} else if (algo.equals("%")) {
result = this.setComponent.number1 % this.setComponent.number2;
} else if (algo.equals("√")) {
result = Math.sqrt(this.setComponent.number1);
}
this.setText(result);
this.addHistory();
// 恢复初始化
this.clearNunber(false, false);
} else if (this.setComponent.number1State && this.setComponent.algo.equals("√")) {
String algo = this.setComponent.algo;
result = Math.sqrt(this.setComponent.number1);
this.setText(result);
this.addHistory();
// 恢复初始化
this.clearNunber(false, false);
}
}
private void addHistory() {
this.setComponent.calcState = true;
if (this.setComponent.isFloat) {
double a = this.setComponent.number1;
String b = "";
if (!this.setComponent.algo.equals("√")) {
b = Double.toString(this.setComponent.number2);
}
String text = "\n" + a + this.setComponent.algo + b + "=" + this.setComponent.jTextField1.getText();
this.setComponent.jTextArea1.setText(this.setComponent.jTextArea1.getText() + text);
} else {
int a = (int) Math.round(this.setComponent.number1);
String b = "";
if (!this.setComponent.algo.equals("√")) {
b = Integer.toString((int)Math.round(this.setComponent.number2));
}
String text = "\n" + a + this.setComponent.algo + b + "=" + this.setComponent.jTextField1.getText();
this.setComponent.jTextArea1.setText(this.setComponent.jTextArea1.getText() + text);
}
}
private void addHistory(String text) {
this.setComponent.jTextArea1.setText(this.setComponent.jTextArea1.getText() + text);
}
@Override
public void actionPerformed(ActionEvent e) {
String name = e.getActionCommand();
String numberS = "1234567890";
String funcS = "÷*-+√%";
String text = this.setComponent.jTextField1.getText();
// 清除内容
if (name.equals("C")) {
this.clearNunber(true, true);
}
// 加减乘除
if (funcS.contains(name)) {
if (this.setComponent.jTextField1.getText().length() == 0 && name.equals("-")) {
this.setComponent.jTextField1.setText("-");
} else {
this.setComponent.jTextField1.setText("");
}
if (this.setComponent.calcState) {
this.setComponent.number1State = true;
this.setComponent.number1 = Double.parseDouble(text);
}
if (this.setComponent.number1State) {
this.setComponent.algo = name;
this.setComponent.selectNumber = 2;
}
}
// 小数点
if (name.equals(".")) {
// 判断是否已经存在小数点
if (!text.contains(".") && text.length() > 0) {
this.setComponent.jTextField1.setText(text + ".");
}
this.setComponent.isFloat = true;
}
// 删除最后一个字符
if (name.equals("Del")) {
if (text.length() > 0) {
String newText = text.substring(0, text.length()-1);
this.setComponent.jTextField1.setText(newText);
}
}
// 判断等于号
if (name.equals("=")) {
// 计算
try {
this.calcNumber();
} catch (Throwable ex) {
String textError = "\n【系统错误】程序运行发生错误\n【错误信息】" + ex + "\n【计算参数】" + this.setComponent.number1 + this.setComponent.algo + this.setComponent.number2 + "\n【联系方式】请将该情况反馈给管理员处理!Smobee";
System.out.println(textError);
addHistory(textError);
JOptionPane.showMessageDialog(null, textError, "系统报错 " + "可联系管理员处理 Smobee", JOptionPane.ERROR_MESSAGE);
}
}
// 判断按键0~9
if (numberS.contains(name)) {
// 判断是不是超过10位
if (text.length() >= 10) {
JOptionPane.showMessageDialog(null,"暂时不支持超过10位数字的计算");
return;
}
// 判断如果当前已经为0,输入0,则不继续增加
if(text.equals("0")) {
return;
}
// 判断是不是结束了计算状态
if (this.setComponent.calcState) {
this.setComponent.jTextField1.setText("");
this.setComponent.calcState = false;
}
// 获取当前文本框的值
String text3 = this.setComponent.jTextField1.getText();
this.setComponent.jTextField1.setText(text3 + name);
String text1 = this.setComponent.jTextField1.getText();
// 判断是第一个数字,还是第二个数字
if (this.setComponent.selectNumber == 1) {
this.setComponent.number1State = true;
this.setComponent.number1 = Double.parseDouble(text1);
} else if (this.setComponent.selectNumber == 2) {
this.setComponent.number2State = true;
this.setComponent.number2 = Double.parseDouble(text1);
}
}
}
}
九、异常处理
我在计算的关键地方,加了异常处理,这样的话,程序就不会闪退,并且提示用户
// 判断等于号
if (name.equals("=")) {
// 计算
try {
this.calcNumber();
} catch (Throwable ex) {
String textError = "\n【系统错误】程序运行发生错误\n【错误信息】" + ex + "\n【计算参数】" + this.setComponent.number1 + this.setComponent.algo + this.setComponent.number2 + "\n【联系方式】请将该情况反馈给管理员处理!Smobee";
System.out.println(textError);
addHistory(textError);
JOptionPane.showMessageDialog(null, textError, "系统报错 " + "可联系管理员处理 Smobee", JOptionPane.ERROR_MESSAGE);
}
}
十、exe4j Wizard 使用生成exe
1. 先在 IntelliJ IDEA 安装Handy Export Jar
2. 然后导出为jar包
通过jar包,我们就可以直接生成exe文件
3. 打开exe4j Wizard
最后一步,生成exe
可以直接打开
更新日志
提示:将会持续优化更新