技术心得记录:基于Swing库的科学计算器设计与开发

简介: 技术心得记录:基于Swing库的科学计算器设计与开发

一、前记


  这是本人第一次作软件的设计与开发,计算器是各个行业的核心组件,我们可以在各个领域看见它的作用。而本软件的目标是解决小学生在学习数学时会遇到的问题/小学生需要学开方吗?/以及完成SIDE(Software integration development environment)课程的第一次作业,由于是给小学生学习使用的(其实是因为写异常类太麻烦),我们需要限制用户的输入。由于是一个简易的小型软件开发并且是第一次开发软件,本次软件工程的流程模型是瀑布模型(如下图),而需求分析已经在作业要求中基本上写好了(加减乘除,牛顿迭代法实现开方,ui界面)故不做赘述。


二、概要设计


  作为一个计算器程序,使用者需要输入数字或符号,最后得到结果,根据这层常识,我们设计出顶层流程图:


  现在我们对流程1(计算器)作进一步的设计,即如何保存待计算数据,如何进行计算。我计划设计一个双栈的计算器内核,将要计算的数字压入栈,再根据待入栈的符号和栈顶符号比较决定哪个符号先投入运算,哪个符号入栈出栈。得到了流程1的一层图:


  具体的计算也需要进一步设计说明,所以对流程2的一层图如下:


三、界面设计即代码


  有了计算的总体流程,我们还要设计计算器的界面布局,我对该软件的布局进行过多次修改,前三个版本由于功能难以实现,功能过少等原因被废除,到下图4,5为最终界面。


在有了界面设计图(上图5)后,我们就要设计出实际界面(上图4)来,根据设计,框架总体为一个固定大小的边缘框架(borderLayout),关键就在于我们框架的大小,为了适配所有的屏幕,框架大小是取决于用户的显示器的,我通过用户显示器的高(考虑到用户可能使用超宽带鱼屏之类的,所以计算器不能超过显示器高)获取一个比例数,而我们计算器界面上所有的大小(按钮大小,窗口大小,甚至是表盘大小)都是由比例数作乘法得到的。框架主题如下(打印的那段编码是一个小彩蛋,可以通过ASCII码破解):


// 获得显示屏大小


public static final int SCREAM_HEIGHT = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();


public static final int SCREAM_WIDTH = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();


// 根据显示屏高度设定计算器界面大小


private static final int EXAMPLE = (int) (SCREAM_HEIGHT / 4.32);


// 字体大小


Font cu = new Font("粗体", Font.BOLD, (int) (EXAMPLE 0.2));


/**超级初始化块**/


protected void init() {


// 设置窗口名称


this.setTitle("计算器");


System.out.println("0b1100001 0b1110101 0b1110100 0b1101000 0b1101111 0b1110010 0b100000 0b1110100 0b1100101 0b1100001 0b1101101 0b100000 0b1101001 0b1110011 0b100000 0b1001110 0b1001111 0b101110 0b110001 0b100000 0b1001110 0b1001111 0b101110 0b111001 0b100000 0b1001110 0b1001111 0b101110 0b110001 0b110011 0b100000 0b1001110 0b1001111 0b101110 0b110010 0b110111 0b100000 0b1001110 0b1001111 0b101110 0b110011 0b110001 0b100000 0b1001110 0b1001111 0b101110 0b110100 0b110001 0b100000 0b1101001 0b1101110 0b100000 0b110010 0b110001 0b1000011 0b1010011");


// 4比3固定窗口


this.setSize(EXAMPLE 3, EXAMPLE 4);


this.setResizable(false);


this.setLocationRelativeTo(null);


// 设置窗口可见


this.setVisible(true);


this.setBackground(Color.black);


// 设置关闭按钮(释放进程)


this.setDefaultCloseOperation(EXIT_ON_CLOSE);


// 设置方向布局


this.setLayout(new BorderLayout());


}


  根据设计图来看,我们在该边缘布局的北面应该设计一个带有计算器屏幕和清除按钮的仪表盘,我在前提里着重说明过,该计算器的最大特色在于限制用户输入,我们的输入输出框自然也是只允许通过按钮输入的。代码如下:


/**北国风光*/


// 北面组件


private JPanel northBox = new JPanel(new FlowLayout());


private JTextField input = new JTextField();


private JButton clear = new JButton();


// 设置北面组件


private void setNorth() {


// 设置数字栏


this.input.setPreferredSize(new Dimension((int) (EXAMPLE 2.2), (int) (EXAMPLE 0.4)));


this.input.setFont(this.cu);


this.input.setForeground(Color.BLACK); // 额好像没用,但限制用户输入更重要


this.input.setEnabled(false);


this.input.setHorizontalAlignment(SwingConstants.RIGHT);


// 设置清空


this.clear.setText("C");


this.clear.setPreferredSize(new Dimension((int) (EXAMPLE 0.4), (int) (EXAMPLE 0.4)));


this.clear.setFont(this.cu);


this.clear.setForeground(Color.RED);


// 安装北仪表


this.northBox.add(this.input);


this.northBox.add(this.clear);


// 安装北仪表到主体


this.add(this.northBox, BorderLayout.NORTH);


}


  根据设计图来看,中部仪表盘的布局是一个网格布局。中部组件数目较多,我们可以通过java的collection类的子类去对每一个按钮的text快速赋值,但是该计算器其实也只设计了45=20个按钮在这里,所以用字符串代替集合类更加方便(如果作大型的计算器则要用集合类,又能增加可读性又方便后续的开发)。但我们有两个特殊的按钮(即pow运算的按钮)它并不是一个字符,根据Linux对代码的评价“代码有三层缩进就需要更改”来看,单独设置第一排按钮是可读性更高的选择,至于为什么要把剩下两个单独字符的也单独做是因为在一开始时我并没有决定好第一排按钮有哪些,怎么放。那么解释完第一排的功能按钮(pow运算和可恶的括号)后,剩下的按钮的text都是单个字符的,我们自然可以用String的切割函数来快速设置。代码如下:


/**中央处理器**/


// 中部组件


private JPanel CPU = new JPanel();


private JButton【】 cal = new JButton【20】;


// 后16个按钮顺序,懒得写集合类了


String str = "789/456x123-0.=+";


// 设置中部组件


private void setCenter() {


// 划分20格


this.CPU.setLayout(new GridLayout(5, 4));


// 设置开方按钮


this.cal【0】 = new JButton();


this.cal【0】.setText("^-2");


this.cal【0】.setPreferredSize(new Dimension((int) (EXAMPLE 0.2), (int) (EXAMPLE 0.15)));


this.cal【0】.setFont(this.cu);


this.cal【0】.setForeground(Color.BLUE);


// 设置括号按钮


this.cal【1】 = new JButton();


this.cal【1】.setText("^2");


this.cal【1】.setPreferredSize(new Dimension((int) (EXAMPLE 0.2), (int) (EXAMPLE 0.15)));


this.cal【1】.setFont(this.cu);


this.cal【1】.setForeground(Color.BLUE);


if (!(version.equals("本计算器由SDT软件开发组开发,小组成员:宋宇昂,邵麟钧,杨斌,苟小兵,白嘉欣,李博宏")))


JOptionPane.showMessageDialog(this, "验证码被修改,您使用的为盗版。\n本计算器由SDT软件开发组开发,小组成员:宋宇昂,邵麟钧,杨斌,苟小兵,白嘉欣,李博宏");


if (!(version.equals("本计算器由SDT软件开发组开发,小组成员:宋宇昂,邵麟钧,杨斌,苟小兵,白嘉欣,李博宏")))


this.dispose();


this.cal【2】 = new JButton();


this.cal【2】.setText("(");


this.cal【2】.setPreferredSize(new Dimension((int) (EXAMPLE 0.2), (int) (EXAMPLE 0.15)));


this.cal【2】.setFont(this.cu);


this.cal【2】.setForeground(Color.BLUE);


// 设置清除按钮


this.cal【3】 = new JButton();


this.cal【3】.setText(")");


this.cal【3】.setPreferredSize(new Dimension((int) (EXAMPLE 0.2), (int) (EXAMPLE 0.15)));


this.cal【3】.setFont(this.cu);


this.cal【3】.setForeground(Color.BLUE);


// 设置后16个按钮


for (int i = 4; i < 20; i++) {


String temp = this.str.substring(i - 4, i - 3);


this.cal【i】 = new JButton();


this.cal【i】.setText(temp);


this.cal【i】.setPreferredSize(new Dimension((int) (EXAMPLE 0.2), (int) (EXAMPLE 0.15)));


this.cal【i】.setFont(this.cu);


if ("+-x/=".contains(temp)) {


this.cal【i】.setForeground(Color.GRAY);


}


}


// 添加按钮


for (int i = 0; i < 20; i++) {


this.CPU.add(this.cal【i】);


}


this.add(this.CPU,BorderLayout.CENTER);


}


上面注释位置有问题也是多次修改第一行按钮的text导致的。


  设计图上专门把南方的模块标出来是因为南方只有一段版本号,不需要表盘,代码如下:


/**南柯一梦*/


public static final String version = "本计算器由SDT软件开发组开发,小组成员:宋宇昂,邵麟钧,杨斌,苟小兵,白嘉欣,李博宏";


// 南面组件


private JLabel message = new JLabel(version, SwingConstants.CENTER);


// 设置南面组件


private void setSouth() {


this.message.setPreferredSize(new Dimension((int) (EXAMPLE 0.1), (int) (EXAMPLE 0.1)));


this.message.setForeground(Color.WHITE);


this.add(this.message, BorderLayout.SOUTH);


}


如果你修改了这段版本号,软件会提示你使用了盗版并释放资源。


四、详细设计


  在详细说明详细设计之前,我们先讲一下对按钮监听,这个功能直接决定了我们详细设计的设计原因,我先对所有按钮本身设置监听,让按钮本身返回监听事件(需要类实现监听的接口),监听事件就是返回按钮的text到函数bigWork,即按钮上的值,代码如下:


/*监听*/


// 给按钮添加监听


private void setListener() {


for (JButton j : cal) {


j.addActionListener(this);


}


this.clear.addActionListener(this);


}


// 监听事件设置


@Override


public void actionPerformed(ActionEvent e) {


String listen = e.getActionCommand();


if ("0.1^23456789+-x/()^-2".contains(listen)) {


this.input.setText(this.input.getText() + listen);


}


this.bigWork(listen);


}


  可以遇见,bigWork就是处理大批数据的地方,也是前端后端所连接的地方,但是在说明该方法前,我要先讲解一下之后会遇到的几种输入状态。之前说过两次,该计算器最大的特色在于限制用户输入,用户已经只能通过按钮输入了,那么限制后用户输入的自然是正确的输入顺序,比如我们输入了一个符号后,就不能再输入符号(因此也不能直接输入减号当负号了,需要输入(0-),不过这样反而能帮助小学生更好得理解负数,后续也可以添加符号按钮),更具我的计算设计,列出以下状态:


根据上表可以编写代码,代码如下:


/*状态**/


// 小数点信号


private Boolean pointSignal = false;


// 括号信号


private int barcketNum = 0;


private String num = "0123456789";


private String sign = "+-x/(";


// 输入的最后一位为数字时的状态,详细见详细设计表格


public void inNum() {


//代码效果参考:http://www.lyjsj.net.cn/wz/art_23751.html

// 只能输入pow函数,右括号,数字和符号按钮,不能输入左括号,若小数点信号为真,则可以输入小数点

for (int i=0;i<20;i++) {


if("(".equals(this.cal【i】.getText())) {


this.cal【i】.setEnabled(false);


}


else {


this.cal【i】.setEnabled(true);


}


}


// 根据信号设置


this.cal【17】.setEnabled(this.pointSignal);


}


// 输入的最后一位为符号或左括号时


public void inSign() {


// 只能输入非小数点数字及左括号,小数点信号开启


for (int i=0;i<20;i++) {


if("(".equals(this.cal【i】.getText()) || this.num.contains(this.cal【i】.getText())) {


this.cal【i】.setEnabled(true);


}


else {


this.cal【i】.setEnabled(false);


}


}


this.pointSignal = true<span style="color: rgba(0, 0, 0

相关文章
|
1月前
|
数据可视化 数据处理 Python
Python数据可视化库Matplotlib的应用与优势探究
本文将深入探讨Python中强大的数据可视化库Matplotlib的应用与优势。通过介绍Matplotlib的基本概念和常用功能,结合具体案例展示其在数据分析和图表绘制中的灵活性和实用性,帮助读者更好地利用这一工具进行数据可视化。
|
8月前
|
供应链 Python
|
1月前
|
数据可视化 大数据 C++
Python数据可视化技术与库:展现数据之美
在大数据时代,数据可视化成为了理解和传达数据的重要手段。本文将介绍Python中两个强大的数据可视化库,Seaborn和Plotly,探讨它们的特点、应用场景和使用方法,帮助读者更好地利用这些工具展现数据之美。
39 2
|
2天前
|
数据采集 JavaScript 前端开发
使用Colly库进行高效的网络爬虫开发
使用Colly库进行高效的网络爬虫开发
|
1月前
|
JavaScript Java 测试技术
基于Java的《数据库系统原理》课程平台的设计与实现(源码+lw+部署文档+讲解等)
基于Java的《数据库系统原理》课程平台的设计与实现(源码+lw+部署文档+讲解等)
33 2
|
1月前
|
JavaScript Java 测试技术
基于Java的少儿编程在线培训系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的少儿编程在线培训系统的设计与实现(源码+lw+部署文档+讲解等)
34 0
|
1月前
|
JavaScript Java 测试技术
基于Java的医院交互系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的医院交互系统的设计与实现(源码+lw+部署文档+讲解等)
27 0
|
1月前
|
监控 Linux 测试技术
嵌入式硬件库的基本操作方式与分析
嵌入式硬件库的基本操作方式与分析
40 0
|
1月前
|
缓存 监控 关系型数据库
构建高效的数据库应用:Python 实践
在当今数据驱动的世界中,构建高效的数据库应用程序对于企业和个人来说至关重要。Python 作为一种强大的编程语言,提供了丰富的数据库工具和库,使得开发人员能够轻松地构建高效、可靠的数据库应用程序。在本文中,我们将探讨一些关键的技术和最佳实践,以帮助你构建高效的数据库应用程序。
|
1月前
|
存储 Python Windows
python 基础综合应用——小开发
python 基础综合应用——小开发