这次的键盘输入我只是完成了基本的加减乘除,sin,cos等函数运算暂时没有考虑,但是这是一个可以用鼠标控制输入也可以键盘输入的计算器,主要功能:
按下home键——清零,清空结果文本框,可重新输入新的数字
按下ESC键——退出计算器
按下backspace键——退格
按下等号/回车——得到计算结果,但是如果按的是等号,结果文本框会多显示一个”=”在最后,但是不影响计算结果正确性。如下图:(界面中右下角hello没有任何功能,只是为了美观)
鼠标输入的逻辑——首先设置当前运算符是=,输入一个数字,然后输入运算符,一旦检测到输入运算符就应该要进入一个处理运算符的函数,然后由于当前运算符是=,就执行等号那部分的程序(仅仅是获得目前输入的第一个数字),然后应该清空文本框,让firstDigit=true,又可以输入数字,并改变当前运算符为刚输入的运算符;再输入等号,又进入处理运算符的那个程序,但是当前运算符应该是刚刚输入的运算符,所以执行+-*/对应的运算程序,得到结果。
键盘输入的逻辑——按下操作数一,显示在文本框中——>按下运算符(+-*/),获取第一个操作数到resultNum中,清空文本框——>显示出运算符,再清除;——>按下操作数2,显示出来,按下等号,就获取操作数二,再做相应的计算得到结果显示出来。
关键是加减乘除四则运算用到的四个布尔变量——plus,sub,mul,div,他们最开始设置为false,一旦检测到相应的运算符按下就变为true,等号按下后根据谁是true做什么运算。
做的过程中遇到一些问题,主要有以下几个:
1. 乘号,加号检测不到。使用if(e.getKeyCode()==KeyEvent.VK_SHIFT&& e.getKeyCode()==61){//加号
System.out.println("你按了+键");
resultNum=getNumberFromText();
resultText.setText("");
plus=true;}是检测不到的,具体解决方法在代码中写的很清楚。
加号应该使用if(e.getKeyChar()=='+'){//加号
System.out.println("你按了+键");
resultNum=getNumberFromText();
resultText.setText("");
plus=true;
}才可以检测到。
2. 加减乘除计算不正确,后来分析原来是因为第二个数字输入以后和运算符一起出现在结果文本框中,当按下等号或者回车时,get到的除了第二个操作数还有运算符,所以结果不对,所以想清除掉运算符的显示,用的代码:
if((e.getKeyCode()>=KeyEvent.VK_0 && e.getKeyCode()<=KeyEvent.VK_9)){
if(e.getKeyChar()=='*'){//乘号,乘号必须放在下面这个if前面,否则就无效,且又必须放在这个检测数字的if语句中才有效,因为按乘号是shift+8,8是数字键,所以加号就不必放在这里
System.out.println("你按了*键");
resultNum=getNumberFromText();
resultText.setText("");
mul=true;
}
if("+-*/".indexOf(resultText.getText())>=0){//非常关键!!!如果检测到结果文本框里面有运算符就清空,这样才不会影响到等号按下后从结果文本框get到的第二个数
resultText.setText("");}}
3. 加号和乘号的顺序问题,这两个不是随便放就有效的,顺序和原因我都写在注释中了,主要是由于加号是shift和=,没涉及到数字,而乘号是shift和8,有数字所以必须放在检测数字的if中(见代码)。
程序:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class KeyTest extends JFrameimplements ActionListener,KeyListener{
privatestatic final long serialVersionUID= 1L;
privatefinal String[] KEYS={
"7","8","9","÷",
"4","5","6","*",
"1","2","3","-",
"0",".","=","+",
"BackSpace","AllClear","Exit","hello"};
privateJTextField resultText=new JTextField("");
privateJButton keys[]=new JButton[KEYS.length];
privateboolean firstDigit=true;
privateboolean plus,sub,mul,div;
privatedouble resultNum=0.0;
//当前运算的运算符,初始化为=
privateString operator="=";
//操作是否合法
privateboolean operateValidFlag=true;
publicKeyTest(){
super("键盘输入测试程序");
System.out.println("构造函数");
init();
}
publicvoid init(){
resultText.setFocusable(true);
JPanelkeyPanel=new JPanel();//创建一个新的面板
keyPanel.setLayout(newGridLayout(5,4,3,3));
for(inti=0;i<KEYS.length;i++){
keys[i]=newJButton(KEYS[i]);//给这 20 个符号创建相应的按钮
keyPanel.add(keys[i]);
keys[i].addActionListener(this);
keys[i].addKeyListener(this);
keys[i].setBackground(Color.black);//设置符号的颜色
keys[i].setForeground(Color.white);//设置符号的颜色
}
resultText.setHorizontalAlignment(JTextField.RIGHT);
resultText.setBackground(Color.white);
JPaneltextPanel =new JPanel();
textPanel.setLayout(newBorderLayout());// 构造一个组件之间没有间距的新边框布局
textPanel.add("Center",resultText);
resultText.addKeyListener(new KeyAdapter(){ //用内部类的方法实现键盘监听
public void keyPressed(KeyEvent e){
super.keyPressed(e);
System.out.println("你按了"+e.getKeyCode()+"键");//通过控制台的输出可以知道自己电脑键盘的每个键的具体编码是多少,方便后面使用,比如减号就是45
if((e.getKeyCode()>=KeyEvent.VK_0 &&e.getKeyCode()<=KeyEvent.VK_9)){
if(e.getKeyChar()=='*'){//乘法,乘号必须放在下面这个if前面,否则就无效,且又必须放在这个检测数字的if语句中才有效,因为按乘号是shift+8,8是数字键,所以加号就不必放在这里
System.out.println("你按了*键");
resultNum=getNumberFromText();
resultText.setText("");
mul=true;
}
if("+-*/".indexOf(resultText.getText())>=0){//非常关键!!!如果检测到结果文本框里面有运算符就清空,这样才不会影响到等号按下后从结果文本框get到的第二个数
resultText.setText("");}}
else if(e.getKeyCode()==KeyEvent.VK_ESCAPE){
System.out.println("退出计算器");
System.exit(0);
}elseif(e.getKeyCode()==0x8){//0x8就是VK_BACK_SPACE
handleBackspace();
}else if(e.getKeyCode()==37){//HOME键
System.out.println("清空计算器");
handleC();
}else if(e.getKeyChar()=='+'){//加号
System.out.println("你按了+键");
resultNum=getNumberFromText();
resultText.setText("");
plus=true;
} else if(e.getKeyCode()==45){//减号
System.out.println("你按了-键");
resultNum=getNumberFromText();
resultText.setText("");
sub=true;
}else if(e.getKeyCode()==47){//除号
System.out.println("你按了/键");
resultNum=getNumberFromText();
resultText.setText("");
div=true;
}
//以下这段程序无法实现功能,检测不到加号,同样这样写也检测不到乘号
/*elseif(e.getKeyCode()==KeyEvent.VK_SHIFT && e.getKeyCode()==61){//加号
System.out.println("你按了+键");
resultNum=getNumberFromText();
resultText.setText("");
plus=true;
}*/
else if(e.getKeyCode()==61 ||e.getKeyCode()==KeyEvent.VK_ENTER){//等号或者回车得到结果,这里或是可以被检测到的,但是前面的与(乘法加法)不行
System.out.println(e.getKeyChar());
System.out.println("你按了=键");
if(plus){resultNum+=getNumberFromText();plus=false;}
elseif(sub){resultNum-=getNumberFromText();sub=false;}
elseif(mul){resultNum*=getNumberFromText();mul=false;}
elseif(div){handleDiv();div=false;}
if (operateValidFlag){
//双精度浮点数的运算
longt1=(long)resultNum;
doublet2=resultNum-t1;
if(t2==0){//相当于结果原来就是整型,而不是双精度
resultText.setText(String.valueOf(t1));//就显示整型即可
}else {//原来就是双精度的
resultText.setText(String.valueOf(resultNum));//显 示成双精度浮点型
}
}
System.out.println(resultNum);
}
firstDigit=true;}});
//整体布局
getContentPane().setLayout(newBorderLayout(5,5));
getContentPane().add("Center",keyPanel);
getContentPane().add("North",textPanel);
Rectanglebounds = this.getBounds();
this.setLocation(500+ bounds.x, 500 + bounds.y);//设置计算器在屏幕上显示的位置
//使得计算器各个组件大小合适
this.pack();
System.out.println("初始化函数");
}
publicvoid keyPressed(KeyEvent ke){System.out.println("键盘按下检测函数");}
publicvoid keyTyped(KeyEvent ke){System.out.println("键盘打字检测函数");}
publicvoid keyReleased(KeyEvent ke){System.out.println("键盘释放检测函数");}
publicvoid actionPerformed(ActionEvent ae){
StringmouseInput =ae.getActionCommand();//当特定于组件的动作(比如被按下)发生时,由组件(比如 Button)生成此高级别事件。事件被传递给每一个 ActionListener 对象,这些对象是使用组件的 addActionListener 方法注册的,用以接收这类事,返回与此动作相关的命令字符串。
handleInput(mouseInput);
}
publicvoid handleInput(String input){
Stringlabel=input;
if("0123456789.".indexOf(label)>=0){
//用户按了数字键或者小数点键
handleNumber(label);
}elseif (label.equals(KEYS[16])){
//如果用户按了退格键
handleBackspace();
}
elseif(label.equals(KEYS[17])){
//用户按了“AC”键(ALL CLEAR)
handleC();
}elseif(label.equals(KEYS[18])){
//用户按了“EXIT” 键(退出计算器)
System.exit(0);
}else{handleOperator(label);
}
}
/**
*处理数字键被按下的事件
*/
privatevoid handleNumber(String key){
System.out.println("handleNumber函数");
if(firstDigit){
//输入的第一个数字
resultText.setText(key);
}
elseif((key.equals("."))&&(resultText.getText().indexOf(".")<0)){
//输入的是小数点,并且之前没有小数点,则将小数点附在结果文本框的后面
resultText.setText(resultText.getText()+key);
}
else{
resultText.setText(resultText.getText()+ key);
}
//以后输入的肯定不是第一个数字了,避免被覆盖掉
firstDigit=false;
}
/**
*处理 Backspace 键被按下的事件
*/
privatevoid handleBackspace(){
System.out.println("handleBackspace函数");
Stringtext=resultText.getText();
inti=text.length();
if(i>0){
//退格,将文本最后一个字符去掉
text=text.substring(0,i-1);
if(text.length()==0){
//如果文本没有了内容,则初始化计算器的各种值
resultText.setText("");
firstDigit=true;//再次输入的数字被认为是第一个,会把之前的0 覆盖
operator="=";//当前运算符改为=
}else{
//显示新的文本
resultText.setText(text);
}
}
}
/**
*处理 C 键被按下的事件
*/
privatevoid handleC(){
System.out.println("handleC函数");
//初始化计算器的各种值,让计算器回到等待输入第一个数字的状态
resultText.setText("");
firstDigit=true;
operator="=";
}
publicvoid handleDiv(){
System.out.println("handleDiv函数");
//除法运算
//如果当前结果文本框的值等于 0
if(getNumberFromText()==0.0){
//操作不合法
operateValidFlag=false;
resultText.setText("除数不能为 0");
}else{
resultNum/=getNumberFromText();
}
}
/**
*处理运算符键被按下的事件
*/
privatevoid handleOperator(String key){
System.out.println("handleOperator函数");
if(operator.equals("÷")){
handleDiv();
}
elseif(key.equals("+")){
//加法运算
resultNum+=getNumberFromText();
}
elseif(operator.equals("-")){
//减法运算
resultNum-=getNumberFromText();
}elseif(operator.equals("*")){
//乘法运算
resultNum*=getNumberFromText();
}
elseif(operator.equals("=")){
//赋值运算
resultNum=getNumberFromText();//当用户输入第一个数后,当前运算符默认为=,所以会把输入的数字 get 到计算中间结果变量中
}
if(operateValidFlag){
//双精度浮点数的运算
longt1;
doublet2;
t1=(long)resultNum;
t2=resultNum-t1;
if(t2==0){//相当于结果原来就是整型,而不是双精度
resultText.setText(String.valueOf(t1));//就显示整型即可
}else{//原来就是双精度的
resultText.setText(String.valueOf(resultNum));//显 示成双精度浮点型
}
}
//运算符等于用户按的按钮
operator=key;
firstDigit=true;
operateValidFlag=true;
}
private double getNumberFromText(){
System.out.println("getNumberFromText函数");
doubleresult=0;
try{
result=Double.valueOf(resultText.getText()).doubleValue();//只要具体的值,不要对象
}
catch(NumberFormatExceptione){
}
returnresult;
}
publicstatic void main(String args[]){
System.out.println("main函数");
KeyTestkt=new KeyTest();
kt.setVisible(true);
kt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}