如何使用方框布局从头开始构建一个Java GUI计算器
在本教程中,我们将使用BoxLayout ,从头开始构建一个计算器,以正确对齐计算器的各个部件。这个计算器将由图形用户界面和执行计算的逻辑部分组成。我们还将学习现实生活中的计算器是如何通过整合加法、减法、除法、乘法等功能在引擎盖下工作的。
作为一个成年人,你可能在某一时刻使用过计算器来计算商业交易,作为一个青少年,解决高中的数学作业,甚至作为一个孩子,用它来玩耍。然而,你有没有问过自己,这些计算器在引擎盖下是如何运作的?如果你很想知道更多这方面的信息,那你就来对地方了。
本教程还将向读者展示BoxLayout ,以及如何在其他程序中使用它,将他们的控制台应用程序转换成GUI应用程序。
先决条件
要跟上进度,最好具备以下条件。
- 具备Java编程语言的基本知识和理解。
- 在Java中使用OOP原则的基本知识。
- 一个合适的集成开发环境(IDE)。
目标
在本教程结束时,读者将。
- 熟练使用
BoxLayout,在Java中构建UI。 - 了解在简单计算器上运行的逻辑。
- 知道如何用Java从头开始构建一个简单的计算器。
布局管理器
布局管理器允许我们在面板上的任何所需位置对齐组件。它们将每个GUI组件定位在其面板或框架上。Java提供的一些布局管理器是开箱即用的。
- GridBag布局
- 网格布局
- 组布局
- 流布局
- 边框布局
- 盒式布局
盒式布局
BoxLayout 是最简单和最容易实现的,仅次于流动布局。它允许你在一列中以垂直盒子的形式将组件堆叠在一起。它还允许在一列中以水平方框的形式 "布置 "组件,彼此相邻。
可以使用JavaSwing 包提供的BoxLayout 类来访问它。这个类的一个新实例被传递到setLayout()面板方法中进行处理。
下面是一个将一个面板的布局设置为BoxLayout 的例子。
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
BoxLayout 构造函数接收了两个参数。第一个是你希望应用布局的容器,第二个参数是由 类提供的常量,它指定了组件将被布置的轴。BoxLayout
下面是一个常数的列表和它们的描述。
| 常数 | 说明 |
|---|---|
public static final int X_AXIS | 指定组件应该从左到右排列。这个常数的值是0 |
public static final int Y_AXIS | 指定组件从上到下排列。这个常数的值是1 |
public static final int LINE_AXIS | 指定组件应该向目标容器的ComponentOrientation 属性所决定的一条线布置。这个常数的值是2。 |
public static final int PAGE_AXIS | 指定组件应该按照目标容器的ComponentOrientation 属性确定的线条在页面上流动的方向布置。这个常数的值是3。 |
注意,你可以使用常数变量或值来设置组件轴。例如,用0代替
BoxLayout.X_AXIS,用1代替BoxLayout.Y_AXIS,还有很多其他的。
我们总是建议使用PAGE_AXIS 和LINE_AXIS 来实现国际化,这将使组件能够根据设备的语言方向从左到右或从右到左正确布局。
虽然BoxLayout 可以单独使用,但你也可以利用Box 类来向面板添加组件。当BoxLayout 单独使用时,组件会粘在一起,没有像padding那样的留白;因此,Box 类发挥了作用。
Box 类提供了静态方法,可以向面板添加不可见的组件,作为组件之间的间距。Box 类提供的一些静态方法是。
createHorizontalBox()createVerticalBox()createRigidArea(Dimension d)createHorizontalGlue()createVerticalGlue()
上面列出的所有方法都可以创建不可见的组件,这些组件之间可以是空白的。现在我们已经了解了BoxLayout ,让我们深入到构建计算器的过程中。
第1步:构建用户界面(UI)

上面的图片是我们将在本教程中构建的计算器的最终视图。
我们首先要创建一个扩展了JFrame 类的计算器类来开始工作。通过扩展JFrame 类,我们要使我们的计算器类继承JFrame 类的所有属性。
注意:
JFrame是一个由 swing 包提供的类。所以我们也需要导入swing包。
import javax.swing.*;
public class CalculatorBox extends JFrame {
}
下一步是创建包含在计算器中的组件。这些组件包括向计算器发送输入的按钮和读取计算器输出的文本字段。我们将使用JButton 和JTextField ,这些组件是由先前导入的摆动包提供的。
除了这些组件,我们还需要创建String 变量,用来保存前一个输入、当前输入和运算符。在类体内添加以下代码作为类变量。
JButton btnAdd, btnSubtract, btnDivide, btnMultiply, btnClear, btnDelete, btnEquals, btnDot;
JButton numBtn[];
JTextField output;
String previous, current, operator;
现在,让我们创建构造函数来初始化组件和变量。我们还将在计算器类内创建main 方法,一旦程序被执行,将调用该类。
回顾一下,
constructor是一个与类同名的方法。因此,我们将使用与我们的类相同的名称来创建构造函数。
public CalculatorBox() {
}
public static void main(String[] args) {
new CalculatorBox();
}
至此,我们已经创建了计算器的基本结构,程序应该是这样的。
import javax.swing.*;
public class CalculatorBox extends JFrame {
JButton btnAdd, btnSubtract, btnDivide, btnMultiply, btnClear, btnDelete, btnEquals, btnDot;
JButton numBtn[];
JTextField output;
String previous, current, operator;
public CalculatorBox() {
}
public static void main(String[] args) {
new CalculatorBox();
}
现在,让我们把重点放在计算器类的构造函数上。我们首先要设置计算器的标题,将标题传入超类(JFrame) 构造函数。在这里,我们要将标题设置为 "方框计算器"。你可以把它设置为你选择的任何名称。在构造函数中添加以下代码。
在构造函数中添加以下代码。
super("Box Calculator");
下一步是创建一个名为mainPanel 的面板,它将容纳计算器中的所有其他组件。
JPanel mainPanel = new JPanel();
由于计算器有一个BoxLayout ,我们可以创建行,然后将计算器的所有组件归入这些行。这些行由位于主面板内的五个子面板组成。面板的层次结构是为了使计算器的设计更加精确。
创建完行后,我们还需要初始化前面声明的组件。这些组件包括输出和其他按钮,如操作和数字按钮。数字按钮已经在一个数组里面了,所以我们在数组的最后追加点按钮。我们将不得不循环浏览数组来初始化按钮,并添加一些样式,这样做是为了避免重复,并实现代码的简洁。
我们将使用Font 类来设计按钮的样式。Font 类是由Java的Abstract Windows ToolKit (AWT)包提供的。这个包包含了其他功能类,我们将在以后的项目中使用。在我们的计算器程序的顶部添加一个导入语句,导入这个包中的所有类。
导入语句的代码如下所示。将代码添加到程序顶部的类声明上方。
import java.awt.*;
回想一下,JButton() ,把String 作为一个参数,用于迭代的计数变量是一个整数。我们将使用String 类的静态方法valueOf() ,将数组中的每个int 值转换为String 。然后我们将分别设置每个按钮的值。类似的造型也适用于计算器的其他按钮。
下面是完整的代码。在构造函数中添加代码,紧接着在mainPanel 变量下面。
// Create sub panels inside main panel
JPanel row1 = new JPanel();
JPanel row2 = new JPanel();
JPanel row3 = new JPanel();
JPanel row4 = new JPanel();
JPanel row5 = new JPanel();
// Initialize components
output = new JTextField(16);
btnSubtract = new JButton("-");
btnAdd = new JButton("+");
btnDivide = new JButton("÷");
btnMultiply = new JButton("*");
btnDot = new JButton(".");
btnEquals = new JButton("=");
btnClear = new JButton("C");
btnDelete = new JButton("D");
// Initialize, style, and add action listeners to number buttons
numBtn = new JButton[11];
numBtn[10] = btnDot;
for (int count = 0; count < numBtn.length - 1; count++) {
numBtn[count] = new JButton(String.valueOf(count));
numBtn[count].setFont(new Font("Monospaced", Font.BOLD, 22));
}
// Style other buttons
btnDot.setFont(new Font("Monospaced", Font.BOLD, 22));
btnEquals.setFont(new Font("Monospaced", Font.BOLD, 22));
btnAdd.setFont(new Font("Monospaced", Font.BOLD, 22));
btnSubtract.setFont(new Font("Monospaced", Font.BOLD, 22));
btnDivide.setFont(new Font("Monospaced", Font.BOLD, 22));
btnMultiply.setFont(new Font("Monospaced", Font.BOLD, 22));
btnClear.setFont(new Font("Monospaced", Font.BOLD, 20));
btnDelete.setFont(new Font("Monospaced", Font.BOLD, 20));
接下来,我们将为输出显示添加一些样式。
// Style the output display
output.setMaximumSize(new Dimension(185, 40));
output.setFont(new Font("Monospaced", Font.BOLD, 27));
output.setDisabledTextColor(new Color(0, 0, 0));
output.setMargin(new Insets(0, 5, 0, 0));
output.setText("0");
到目前为止,我们已经创建了显示在计算器中的组件并进行了样式设计。然而,这些组件是不可见的,除非添加到它们各自的面板和主面板上。下一步是设置计算器的每一行的布局。
每一行都被设置为BoxLayout ,布局方向为LINE_AXIS 。我们将根据所使用设备的语言方向,使按钮从左到右或从右到左流动。
// Set the layout of each row in the pane
row1.setLayout(new BoxLayout(row1, BoxLayout.LINE_AXIS));
row2.setLayout(new BoxLayout(row2, BoxLayout.LINE_AXIS));
row3.setLayout(new BoxLayout(row3, BoxLayout.LINE_AXIS));
row4.setLayout(new BoxLayout(row4, BoxLayout.LINE_AXIS));
row5.setLayout(new BoxLayout(row5, BoxLayout.LINE_AXIS));
在设置了每个子面板的布局后,我们现在必须添加相应的组件来填充这些子面板。
请注意,这可以像我们为数字按钮所做的那样,用一个循环来实现。但为了简单起见,我们只需要按顺序添加组件。
// Add components to each of the row
row1.add(Box.createHorizontalGlue());
row1.add(btnClear);
row1.add(btnDelete);
row2.add(numBtn[7]);
row2.add(numBtn[8]);
row2.add(numBtn[9]);
row2.add(btnMultiply);
row3.add(numBtn[4]);
row3.add(numBtn[5]);
row3.add(numBtn[6]);
row3.add(btnAdd);
row4.add(numBtn[1]);
row4.add(numBtn[2]);
row4.add(numBtn[3]);
row4.add(btnSubtract);
row5.add(btnDot);
row5.add(numBtn[0]);
row5.add(btnEquals);
row5.add(btnDivide);
请注意,我们创建了一个水平胶水,并将其作为第一个组件添加到row1 中。这个水平胶水将C 和D 按钮尽可能地推到窗格的水平边缘。

你也可以用createVerticalGlue() 来实现类似的效果。但它不是迫使其左右两边的组件尽可能地远离对方,而是迫使上下两边的组件尽可能地远离对方。
在完成用户界面之前的第二至最后一步是设置主面板的布局,然后按照主面板的要求添加所有各自的行。在这里,我们将把主布局方向设置为PAGE_AXIS ,它将面板中的组件从上到下排列。
我们还将在输出显示和按钮之间添加一个空间,以便在用户界面中实现适当的间距。这个空间是使用Box类的createRigidArea() 方法添加的,它需要一个Dimension 。Dimension ,需要两个参数,第一个参数是宽度,第二个是高度(像素)。在这里,我们在输出显示和其他按钮之间增加5个像素。
下面是完成上述所有工作的代码。
// Add all rows to the main panel
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
mainPanel.add(output);
mainPanel.add(Box.createRigidArea(new Dimension(0, 5)));
mainPanel.add(row1);
mainPanel.add(row2);
mainPanel.add(row3);
mainPanel.add(row4);
mainPanel.add(row5);
UI已经完成。然而,如果你运行这段代码,框架将显示为空,因为我们还没有添加主面板。我们可以通过使用JFrame的add() 方法来实现这一点。我们还需要设置当用户点击close 按钮时会发生什么。这里,它将退出应用程序。
此外,我们需要将应用程序的可见性设置为true ;否则,它将是透明的,因此是不可见的。为了使应用程序成形,我们需要使用来自JFrame 的setSize() 方法来设置尺寸。该方法接收两个参数:第一个是宽度,第二个是高度。
下面是结束UI设计的代码。
// final touch
this.add(mainPanel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.setSize(205, 280);
我们的计算器的用户界面已经完成,可以启动了。下面是计算器的最终视图的图片。

第2步:开发计算器的逻辑
现在,我们已经完全构建了计算器的用户界面。下面的步骤是为按钮添加功能并建立计算器的逻辑。
2.1 创建结构
首先,我们将创建一些实用的方法,来定义计算器的各种功能。这些方法都是在类内定义的,但在构造函数之外。然后,我们将在进行过程中逐步建立这些方法的功能。
下面是实用方法的代码。
public void delete() {
}
public void clear() {
}
public void updateOutput(){
}
public void appendToOutput(String num) {
}
public void selectOperator(String newOperator) {
}
public void calculate() {
}
下一步是为这些按钮中的每一个创建ActionListeners 。这些动作监听器使按钮监听事件,如当用户点击按钮时,然后更新输出和其他必要的字段。
在本教程中,我们将使用一个实现ActionListener 接口的内部类。我们将使所有的类成为私有的。ActionListener 接口是由Java的AWT事件包提供的。除了ActionListener ,我们将在本教程的后面需要事件包中的其他接口。
让我们在文件的顶部添加一个导入语句,导入事件包中的所有类和接口。
import java.awt.event.*;
下一步是创建这些匿名的类,它们将处理计算器中的事件。我们将创建三个类来处理计算器中的所有点击事件。
2.2 创建事件处理程序
- **'class NumberBtnHandler'**第一个类是
NumberBtnHandler,它将处理所有数字按钮的事件,包括点按钮。这个类将实现ActionListener接口来覆盖ActionListener接口中的actionPerformed()抽象方法。这个方法接收一个ActionEvent参数,这个参数是由前面导入的事件包提供的。
下面是NumberBtnHandler 类的代码。紧接着将代码添加到实用方法的下面。
private class NumberBtnHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
}
}
接下来,我们必须决定当任何一个 "数字按钮 "被点击时将会发生什么,这可以在actionPerformed() 方法中实现,该方法接收了一个我们命名为e 的参数。然后,参数e 可以访问ObjectsgetSource() 方法,以获得事件最初发生的对象,这在检查被点击的按钮时很有用。
回顾一下,"数字按钮 "是在一个数组里面。所以我们可以很容易地在数组中循环,将每个按钮与被点击的按钮进行比较。如果出现匹配,我们就会得到按钮里面的文本,并将其追加到输出显示中。之后,我们将调用updateDisplay() 方法来显示新附加的数字。
请注意,我们需要将
e.getSource()转为JButton,以将其存储在一个名称更有意义的按钮变量中,以后可以在循环中用于比较。
下面是实现的代码。请注意,下面所有的代码行都在NumberBtnHandler 类的actionPerformed() 方法内。
JButton selectedBtn = (JButton) e.getSource();
for (JButton btn : numBtn) {
if (selectedBtn == btn) {
appendToOutput(btn.getText());
updateOutput();
}
}
- **'class OperatorBtnHandler'**第二个要创建的类是
OperatorBtnHandler,它也实现了ActionListener接口。这个类类似于上面创建的NumberBtnHandler,但重要的区别在于actionPerformed()方法里面。
在这个类的actionPerformed() 方法中,我们将比较每个操作者按钮和被点击的按钮,以了解哪个操作者被选中。我们可以使用if语句来实现这一点,因为运算符按钮不在一个数组内,不像 "数字按钮 "那样。
当一个运算符按钮被选中时,我们获得按钮的文本,将其传递给selectOperator() 方法,并通过调用updateOutput() 方法更新输出。下面是OperatorBtnHandler 类的代码实现。
private class OperatorBtnHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton selectedBtn = (JButton) e.getSource();
if (selectedBtn == btnMultiply) {
selectOperator(btnMultiply.getText());
} else if (selectedBtn == btnAdd) {
selectOperator(btnAdd.getText());
} else if (selectedBtn == btnSubtract) {
selectOperator(btnSubtract.getText());
} else if (selectedBtn == btnDivide) {
selectOperator(btnDivide.getText());
}
updateOutput();
}
}
class OtherBtnHandler最后一个要创建的动作监听器类是OtherBtnHandler类。这个类也将实现ActionListener接口并重写actionPerformed()方法。类似于OperatorBtnHandler,OtherBtnHandler将比较所选按钮和计算器中的其他按钮,并执行它们各自的方法。
执行后,我们也将调用outputDisplay() 方法来更新用户界面。下面是OtherBtnHandler类的代码实现。下面是OtherBtnHandler 类的完整实现。
private class OtherBtnHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e ) {
JButton selectedBtn = (JButton) e.getSource();
if (selectedBtn == btnDelete) {
delete();
} else if (selectedBtn == btnClear) {
clear();
} else if (selectedBtn == btnEquals) {
calculate();
}
updateOutput();
}
}
2.3 为按钮添加动作监听器
我们刚刚创建了所有的动作监听器,这些监听器将处理来自所有计算器的按钮的所有事件。然而,如果你现在点击任何一个按钮,都不会有事件发生,因为这些动作监听器还没有被添加到相应的按钮上。
现在回到我们的构造函数。第一步是创建所有按钮处理类的对象,然后将其作为动作监听器传递给每个按钮。紧接着添加以下代码,在构造函数中我们首先初始化组件。准确地说,在我们初始化btnDelete 。
// Instantiate action listeners
NumberBtnHandler numBtnHandler = new NumberBtnHandler();
OtherBtnHandler otherBtnHandler = new OtherBtnHandler();
OperatorBtnHandler opBtnHandler = new OperatorBtnHandler();
下一步是将这些动作监听器添加到各自的按钮中。回想一下我们在上面用于样式数字按钮的循环。你可以直接在循环中为每个按钮添加动作监听器,类似于添加样式的方式。你可以通过调用每个按钮的addActionListener() 方法并传递各自的动作监听器来实现。
用下面的代码更新整个循环的主体。
for (int count = 0; count < numBtn.length - 1; count++) {
numBtn[count] = new JButton(String.valueOf(count));
numBtn[count].setFont(new Font("Monospaced", Font.BOLD, 22));
numBtn[count].addActionListener(numBtnHandler);
}
同样,如下图所示,你可以通过向每个按钮的addActionListener() 方法传入各自的动作监听器来为操作和其他按钮添加动作监听器。
// Add action listeners to other buttons
btnDot.addActionListener(numBtnHandler);
btnDelete.addActionListener(otherBtnHandler);
btnClear.addActionListener(otherBtnHandler);
btnEquals.addActionListener(otherBtnHandler);
// Add action listeners to operation buttons
btnMultiply.addActionListener(opBtnHandler);
btnAdd.addActionListener(opBtnHandler);
btnSubtract.addActionListener(opBtnHandler);
btnDivide.addActionListener(opBtnHandler);
紧接着在对输出进行样式处理的那一行下面添加上述代码。
这一行正是。
output.setText("0");
计算器中的所有按钮现在都有功能了,但是如果你点击任何一个按钮,你还不会看到输出。这是因为我们将用来辅助这些功能的方法现在是空的。让我们深入研究并更新这些方法。
2.4 更新实用方法
- **'updateOutput()'**我们要更新的第一个方法是
updateOutput()方法。这个方法用当前操作数的值更新输出显示。在updateOutput()方法中加入下面这行代码。
output.setText(current);
- **'appendToOutput()'**接下来,我们将更新
appendToOutput()方法。这个方法将用户点击的任何数字添加到输出变量中。我们将通过串联用户输入到输出的当前值,然后再更新输出来实现这一目标。
在appendToOutput() 方法内添加下面这行代码,并运行程序以查看输出结果。
current += num;
下面的图片是计算器的更新视图。

如果仔细研究,你会发现计算器有两个问题。首先,在输出显示中出现一个null ,后面还有其他数字。第二个问题是添加超过一个点,这不适用于标准计算器。让我们来快速解决这个问题。
为了解决输出显示中的多个点,用下面的代码替换appendToOutput() 方法里面的代码。
public void appendToOutput(String num) {
// Prevents adding more than one dot on the output
if (num.equals(".") && current.contains(".")) {
return;
}
current += num;
}
该代码将首先检查当前输出上是否有一个点。如果已经有一个,它将返回而不执行该函数。然而,如果没有,它将把输入的点添加到当前显示中。
为了解决输出显示中出现的null,请记住String 的默认值是null 。所以当我们在程序顶部声明当前变量时,默认变量会被分配给它。
为了解决这个问题,我们在构造函数中把current和previous的值都初始化为一个空字符串。这将在程序执行后立即初始化这些变量的值。
在程序的顶部添加以下代码,就在我们创建mainPanel 变量的地方下面。
// Initializing the calculator operands
current = "";
previous = "";
现在我们已经修复了输出显示的小错误,我们可以更新其他计算器方法。
clear()和delete()下一组要更新的方法是clear()和delete()。clear()方法通过将前一个和当前的操作数都设置为空字符串来清除屏幕上的所有内容。它还将operator设置为空,这样我们就不能对一个空的String。
delete() 方法从输出显示中移除最后一个索引的元素,这是通过使用substring() 方法从字符串中的第一个到旁边的最后一个元素来实现的,然后将其设置为输出显示中新的当前操作数。
只用这种delete() 方法的实现,如果你在输出为空时点击删除按钮,你会得到一个StringIndexOutOfBoundsException ,因为你试图从一个空字符串中砍掉最后一个元素。
为了解决这个问题,我们将设置一个if 条件,让删除方法主体只在字符串至少包含一个元素时才运行。下面是clear() 和delete() 方法的代码。
public void delete() {
if (current.length() > 0) {
current = current.substring(0, current.length() - 1);
}
}
public void clear() {
current = "";
previous = "";
operator = null;
}
selectOperator()接下来,让我们考虑一下selectOperator()方法,我们将用它来根据用户的输入设置运算符。在设置运算符之前,需要做一些检查。首先,假设输出是空的,并且选择了一个运算符。
在这种情况下,我们将把新的运算符设置为所选的运算符,注销之前输入的运算符,然后退出该方法,当用户不小心点击了错误的运算符时,这很有用。然后可以通过点击下一个正确的运算符来进行纠正。
另一个检查是看前面的操作数是否为空。如果为真,我们将在选择下一个运算符之前,用当前的运算符评估前一个运算符。这就是为什么用户不用按等号按钮就能连续进行计算的原因。
例如,当用户输入1 + 2 ,而不是按下等号按钮,用户会执行更多的操作,例如+ 3 。该方法将首先评估前两个操作数的值,并在选择下一个操作数之前将结果设置为当前操作数。
在所有的检查完成后,我们现在将把新的运算符设置为所选的运算符,并将输出上显示的当前运算符的值传递给上一个运算符。我们还将通过将当前操作数设置为空字符串来清除屏幕,从而给出新的输入。
下面是selectOperator() 方法的代码实现。
public void selectOperator(String newOperator) {
// if no number is entered yet
if (current.isEmpty()) {
operator = newOperator;
return;
}
if (!previous.isEmpty()) {
calculate();
}
operator = newOperator;
previous = current;
current = "";
}
计算()
我们要研究的最后一个方法是calculate() ,它将执行计算器中的所有计算。我们将确认前一个和当前操作数的值都不是空的。如果任何一个或两个操作数都是空的,计算将不成立,因为我们需要这两个操作数来进行任何算术计算。
然后我们将创建一个名为result的浮点变量,并将其初始化为0.0。我们需要对结果进行初始化,以防编译器想把结果解析成一个字符串。在switch case语句中用于初始化结果值的运算符的值可能没有被初始化。这就使得结果没有被初始化,在试图将其解析为字符串时,会出现错误。
下一步是将前一个和当前的操作数从字符串解析为双数进行计算。现在我们已经得到了前一个和当前的操作数以及用于它们的运算符。下一步是使用switch语句根据运算符计算前一个和当前一个操作数的结果,然后存储结果。
calculate() 方法的最后一步是将浮点结果转换为字符串并将其值传递给当前操作数。然后将运算符的值设置为空,因为运算符已经被用来进行计算了。然后我们可以清除前一个操作数,这样它的值就不会再被用来进行计算,因为它已经被使用过了。
下面是calculate() 方法的最终代码实现。
public void calculate() {
if (previous.length() < 1 || current.length() < 1) {
return;
}
double result = 0.0;
double num1 = Double.parseDouble(previous);
double num2 = Double.parseDouble(current);
switch (operator) {
case "*":
result = num1 * num2;
break;
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "÷":
result = num1 / num2;
break;
default:
break;
}
current = String.valueOf(result);
operator = null;
previous = "";
}
现在你可以运行该程序了,计算器如期工作。你也可以执行你选择的任何计算,并得到正确的结果。
第3步
现在,你的计算器已经完全正常,并输出了正确的结果。然而,还有一个事实,你可能不喜欢这个计算器,它不能正确显示整数,就像下面的图片一样。

上面的图片是执行随机操作的结果,如4 * 56 。由于结果是一个整数,所以我们不需要额外的尾部零。
processOutputNumber()。为了解决这个问题,我们创建了一个名为processOutputNumber() 的方法来处理输出上显示的每一个数字。
为了避免处理一个空的输出,我们将首先使用if语句检查当前输出是否为空。然后我们将把输出分成两部分--整数和小数部分。我们可以使用String 类的split() 方法来实现这一点,然后传入一个正则表达式,在输出中搜索一个点。
记得split() 方法返回一个数组,将数组的第一个元素设置为integerPart ,第二个元素设置为decimalPart 。然后我们将检查小数部分是否为0 。我们忽略它,只将整数部分设置为当前输出,如果true 。
下面是processOutputNumber() 方法的最终代码。
public void processOutputNumber() {
if (current.length() > 0) {
String integerPart = current.split("\\.")[0];
String decimalPart = current.split("\\.")[1];
if (decimalPart.equals("0")) {
current = integerPart;
}
}
}
最后一步是在calculate() 方法的最后一行调用processOutputNumber() 方法,因为我们想在显示数字之前随时处理显示在输出端的数字。

processOutputNumber()与其他实用方法处于同一级别。
现在你可以用涉及整数的计算来测试计算器,也可以用小数的结果来测试计算器。


上面的图片分别是计算4 * 56 和24 ÷ 5 的结果。
就这样吧!
恭喜你使用Java中的BoxLayout 建立了一个功能齐全的计算器。
总结
本教程的主要目的是创建一个可以进行基本算术运算的计算器,并添加了一些功能,如使用BoxLayout 删除和清除输出。你可以为这个计算器添加更多的功能,如科学运算。
你还可以通过将我们的计算器用户界面转换为更复杂的布局,类似于科学计算器的用户界面来探索BoxLayout 。利用这些知识,你可以做很多事情。我希望看到你会用它来构建伟大的东西。