按钮输入运算符,界面显示等式,可输出运算结果。
可见查查运算历史,检查运算式的合法性。
可实现四则运算,加减乘除括号等。
可满足小数运算。
实验预习
Java Swing的简单操作
1.JPanel:
面板组件,非顶层容器
一个界面只有一个JFrame窗体组件,但可以有多个JPanel面板组件,而JPanel上也可以使用布局管理器,这样组合可以达到比较复杂的布局效果
注意事项:
1.JPanel是JComponent的子类
2.属于容器类组件,可以加入别的组件
3.默认布局管理器是FlowLayout
2.button:
push”button.button 的实现可以通过操作进行配置,并在一定程度上进行控制。使用带按钮的动作有许多好处,不仅仅是直接配置按钮。
JButton():建立一个按钮。
JButton(Icon icon):建立一个有图像的按钮。
JButton(String icon):建立一个有文字的按钮。
JButton(String text,Icon icon):建立一个有图像与文字的按钮。
3.this.setTitle("多种布局格式"); //框架标题;
4.this.setSize(400,200); //框架尺寸;
5.this.setLocation(300,300); //框架坐标;
6.this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //关闭操作按钮的设置
7.this.setVisible(true); //框架可视化
8.BorderLayout; // 向边框里添加组件。边界布局展示了一个容器,安排和调整其组件以适应五个区域: 北部、南部、东部、西部和中心。每个区域可能包含不超过一个组成部分,并由一个相应的常量标识: 北、南、东、西和中心。当向具有边框布局的容器添加组件时,使用以下五个常量之一,例如: panel p = new panel () ; p.setlayout (new borderlayout ()) ; p.add (new button (“ okay”) ,borderlayout.south) ;
9.pack //使窗口的大小适合其子组件的首选大小和布局。如果任何一个窗口的尺寸小于之前调用 setminimumsize 方法所指定的最小尺寸,则窗口的宽度和高度将自动放大。
10.setLayout创建一个布局管理器,
具有指定的对齐方式以及指定的水平和垂直间隙。
对齐参数的值必须是以下之一:FlowLayout.LEFT、FlowLayout.RIGHT、FlowLayout.CENTER、FlowLayout.LEADING 或 FlowLayout.TRAILING。
参数:
align - 对齐值
hgap - 组件之间以及组件与 Container 的边之间的水平间隙
vgap - 组件之间以及组件与 Container 的边之间的垂直间隙
11.JFrame 类与 Frame 稍微不兼容。 与所有其他 JFC/Swing 顶级容器一样,JFrame 包含一个 JRootPane 作为其唯一子项。 根窗格提供的内容窗格通常应包含 JFrame 显示的所有非菜单组件。 这与 AWT Frame 情况不同。 为方便起见,重写了此类的 add、remove 和 setLayout 方法,以便它们将调用委托给 ContentPane 的相应方法。
12.Java 框架教程:
如何制作框架(主窗口)(Java™教程>使用 Swing >创建 GUI 使用 Swing 组件) (oracle.com)
13.实现算法为双栈, public static Stack<String> num = new Stack<>();//定义数字栈。
public static Stack<String> operator = new Stack<>();//定义运算符栈。
实现代码:
import java.awt.*;//包含用于创建用户界面和绘制图形和图像的所有类。
import java.awt.event.*;//提供接口和类来处理由 AWT 组件触发的不同类型的事件。
import java.util.Stack;
import javax.swing.*;
class Calculator extends JFrame implements ActionListener {//接收动作事件的监听器接口。
static Calculator frm = new Calculator();//定义框架frm。
static JPanel pan1 = new JPanel();//定义放置数字等按钮的容器。
static JPanel pan2 = new JPanel();//定义放置其他按钮的容器。
static JTextField pan3 =new JTextField();//可编辑的文本框显示历史记录。
static JTextField tf = new JTextField("0");//定义计算结果显示框初始为'0'。
static JTextField RET=new JTextField();//定义运算式的显示框。
static JButton[] b = new JButton[10];//定义10个按钮数组。
static JButton bp, ba, bs, bm, bd, be, bc, br,qf,ds;//定义其他运算符按钮。
String expression = new String();//定义字符串,用于保存输入的表达式。
int flash=0;
public static void main(String[] args) {
for (int i = 0; i <= 9; i++)
b[i] = new JButton("" + i);//给每个按钮赋值。
bp = new JButton(".");
ba = new JButton("+");
bs = new JButton("-");
bm = new JButton("*");
bd = new JButton("/");
be = new JButton("=");
bc = new JButton("c");
br = new JButton("<--");
qf=new JButton("(");
ds=new JButton(")");
frm.setTitle(" 天河三号");//给框架设标题。
frm.setLayout(null);//设置布局管理器,具有指定的对齐方式以及指定的水平和垂直间隙。
frm.setSize(450, 340);//设定frm的大小。
frm.setResizable(false);//设定为大小不可更改。
GridLayout grid1 = new GridLayout(4, 4);//用于在矩形网格中布置容器的组件。此处为四行四列的矩阵网格。
GridLayout grid2 = new GridLayout(1, 4);//容器被分成大小相等一行四列的矩形,每个矩形中放置一个组件。
pan1.setLayout(grid1);//将第一个按钮容器分为四行四列。
pan2.setLayout(grid2);
RET.setBounds(32,10,280,30);
tf.setBounds(32,38, 280, 35);//设置结果框大小。
pan1.setBounds(32, 80, 280, 160);
pan2.setBounds(32, 240, 280, 40);//设置容器大小。
pan3.setBounds(312,10,95,270);
tf.setBackground(Color.green);//设置结果框背景颜色。
tf.setHorizontalAlignment(JTextField.RIGHT);//设置结果框从右边输入。
RET.setBackground(Color.cyan);//设置表达式框背景颜色。
RET.setText("请输入正确的表达式");//RET框的默认显示。
RET.setHorizontalAlignment(JTextField.RIGHT);//RET框从右边输出。
pan3.setBackground(Color.lightGray);//上条历史记录框的颜色。
pan1.add(b[7]);pan1.add(b[8]);pan1.add(b[9]);pan1.add(bd);
pan1.add(b[4]);pan1.add(b[5]);pan1.add(b[6]);pan1.add(bm);
pan1.add(b[1]);pan1.add(b[2]);pan1.add(b[3]);pan1.add(bs);
pan1.add(b[0]);pan1.add(bp);pan1.add(be);pan1.add(ba);
pan2.add(bc);pan2.add(qf);pan2.add(ds);pan2.add(br);//给容器矩阵中加入按钮。
frm.add(tf);//将容器框都加入frm框架。
frm.add(RET);
frm.add(pan1);
frm.add(pan2);
frm.add(pan3);
for (int i = 0; i <= 9; i++)//按钮与监听接口的连接。
b[i].addActionListener(frm);
bd.addActionListener(frm);
bm.addActionListener(frm);
bs.addActionListener(frm);
ba.addActionListener(frm);
bc.addActionListener(frm);
br.addActionListener(frm);
bp.addActionListener(frm);
be.addActionListener(frm);
qf.addActionListener(frm);
ds.addActionListener(frm);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setVisible(true);
} //界面设计;
String S1;
String S2;
static int f=0;
public void actionPerformed(ActionEvent e) {//处理监听信号做出行为
if(expression.isEmpty()){
if(e.getActionCommand()=="."){//开头输'.'前面补“0".
expression="0"+e.getActionCommand();
flash=1;
}
else if(e.getActionCommand()=="-"){
expression="0-"+expression;//开头输'-'变为负数。
tf.setText(expression);
}
else if(e.getActionCommand()=="(")expression+=e.getActionCommand();//
}
if (e.getActionCommand().equals("=")) {
if(expression.charAt(expression.length() - 1) == '.')expression=expression+"0";
if( expression.charAt(expression.length() - 1) != '-' &&
expression.charAt(expression.length() - 1) != '+' &&//等号之前不能有运算符及右括号。
expression.charAt(expression.length() - 1) != '*' &&
expression.charAt(expression.length() - 1) != '/' &&
expression.charAt(expression.length() - 1) != '(' )
{
S1=expression;
RET.setText(expression+"=");
expression = Calculate.count(expression);
S2=expression;
tf.setText(expression);
if(expression.charAt(0)=='-')expression="0"+expression;
} }
else if (e.getActionCommand().equals("c")) {
expression =""; //按'c'键表达式置空
tf.setText("0");
flash=0;
pan3.setText(S1+"="+S2);
RET.setText("请输入正确的表达式");//RET框恢复默认。
}
else if (e.getActionCommand().equals("<--")) {
expression = expression.substring(0, expression.length() - 1);
tf.setText(expression);//用于删除表达式最后一个字符。
}
else if(e.getActionCommand().equals("+") ||
e.getActionCommand().equals("-") ||
e.getActionCommand().equals("*") ||
e.getActionCommand().equals("/") ||
e.getActionCommand().equals(")")
)
{
if ( expression.charAt(expression.length() - 1) != '-' &&
expression.charAt(expression.length() - 1) != '+' &&//设置符号不能连续输入。
expression.charAt(expression.length() - 1) != '*' &&
expression.charAt(expression.length() - 1) != '/'
)
{
if(expression.charAt(expression.length() - 1) == '.'){
expression=expression+"0"+e.getActionCommand();//运算符前面是'.'自动补'0'。
}
else if(expression.charAt(expression.length()-1)=='('&&e.getActionCommand().equals("-")){
expression=expression+"0-";}//左括号后面允许输负号。
else if(e.getActionCommand().equals("*")||
e.getActionCommand().equals("/")||
e.getActionCommand().equals("+"))
{ if(expression.charAt(expression.length()-1)!='(')//'('后不能输运算符。
expression=expression+e.getActionCommand();tf.setText(expression);
}
else if(e.getActionCommand().equals(")")){
if(expression.charAt(expression.length()-1)!='(' &&
expression.charAt(expression.length()-1)!=')'&&
expression.contains("(")) {
expression+=e.getActionCommand();//括号内容不能为空。
}
}
else expression+=e.getActionCommand();flash=0;
}
tf.setText(expression);
}
else if(e.getActionCommand().equals(".")) {
if(flash==0){
if (expression.charAt(expression.length() - 1) == '(' ||
expression.charAt(expression.length() - 1) == '+' ||
expression.charAt(expression.length() - 1) == '-' ||
expression.charAt(expression.length() - 1) == '*' ||
expression.charAt(expression.length() - 1) == '/' ){
expression = expression + "0" + e.getActionCommand();
}
//运算符后面输'.'自动补'0'。
if(expression.charAt(expression.length() - 1) != '.'){
expression+=e.getActionCommand();//'.'不能连续输入。
}
}tf.setText(expression);
flash=1;
}
else if(e.getActionCommand().equals("(")){
if(expression.charAt(expression.length() - 1) == '+' ||
expression.charAt(expression.length() - 1) == '-' ||
expression.charAt(expression.length() - 1) == '*' ||
expression.charAt(expression.length() - 1) == '/'
)expression=expression+e.getActionCommand();
tf.setText(expression);
}
else {
expression += e.getActionCommand();
tf.setText(expression);
}
}
static class Calculate {
public static Stack<String> num = new Stack<>();//定义数字栈。
public static Stack<String> operator = new Stack<>();//定义运算符栈。
public static Stack<String> operator2=new Stack<>();
public static Stack<String> num2=new Stack<>();
public static void work() {//括号外的计算函数。
String s2 = num.pop();
String s1 = num.pop();
float num2 = Float.parseFloat(s2);
float num1 = Float.parseFloat(s1);
String op = operator.pop();
float num3;
switch (op) {
case "+":
num3 = num1 + num2;
num.push(num3 + "");
break;
case "-":
num3 = num1 - num2;
num.push(num3 + "");
break;
case "*":
num3 = num1 * num2;
num.push(num3 + "");
break;
case "/":
num3 = num1 / num2;
num.push(num3 + "");
break;
}
}
public static void work2() {//括号内的计算函数。
String s2 = num2.pop();
String s1 = num2.pop();
float num4 = Float.parseFloat(s2);
float num3= Float.parseFloat(s1);
String op = operator2.pop();
float num5;
switch (op) {
case "+":
num5 = num3 + num4;
num2.push(num5 + "");
break;
case "-":
num5 = num3 - num4;
num2.push(num5 + "");
break;
case "*":
num5 = num3 * num4;
num2.push(num5 + "");
break;
case "/":
num5 = num3 / num4;
num2.push(num5 + "");
break;
}
}
public static String count(String s) {
int i = 0;
while (i < s.length()) {
switch (s.charAt(i)) {
case '+':
case '-':
while (!operator.empty()) {
work();//运算符栈非空进行运算。
}
operator.push(s.charAt(i) + "");
i++;
break;
case '*':
case '/':
while (!operator.empty() && (operator.peek().equals("*") || operator.peek().equals("/"))) {
work();
System.out.println("Ok");
}
operator.push(s.charAt(i) + "");
i++;
break;
case '('://计算括号内的值。
f=1;
i++;
while (s.charAt(i)!=')') {//
switch (s.charAt(i)) {
case '+':
case '-':
while (!operator2.empty()) {
work2();
}
operator2.push(s.charAt(i) + "");
i++;
break;
case '*':
case '/':
while (!operator2.empty()&& (operator2.peek().equals("*")
|| operator2.peek().equals("/"))) {
work2();
System.out.println("Ok");
}
operator2.push(s.charAt(i) + "");
i++;
break;
default:
String number = "";
for (; s.charAt(i) != ')' && (s.charAt(i) >= '0' && s.charAt(i) <= '9'
|| s.charAt(i) == '.'); i++) {
number = number + s.charAt(i);
}
num2.push(number);
}
}
if(s.charAt(i)==')')f=0;
i++;
while (!operator2.empty()) {
work2();
}
num.push(num2.peek());
break;
default:
String number = "";
for (; i < s.length() && (s.charAt(i) >= '0' && s.charAt(i) <= '9' || s.charAt(i) == '.'); i++) {
number = number + s.charAt(i);
}
num.push(number);
}
}
while (!operator.empty()) {
work();
}
return num.peek();//返回栈顶的运算结果。
}
}
}