首先建了一个JFrame的子类Show,在这个子类里面建了一个JPanel的内部子类MyPanel,Show显示的就是MyPanel的内容。通过画线,每次线颜色的rgb根据循环的i值做出相应的改变,从而实现了背景的渐变。后面根据一些Show的一些属性开始画网格,并且通过主函数的监听事件传入的坐标,在实现按键的效果(响应位置重画其它颜色)。根据位置把对应的符号传入Deal类进行运行。最后MyPanel画上Deal上的有关值的属性。
Main类就只要是设置号监听事件,传入被点击的坐标。刚开始使用的是mouseClick 但发现如果按下和抬起的坐标不一直,则这次点击无效,造成一种卡顿的假想。所以我用了mousePressed和mouseReleased这两个方法。
Deal类就是用于处理计算,Change方法是存入数值,防止非法输入。最麻烦的就是中缀转换为后缀的那个算法。
中缀转换为后缀思路请见:http://blog.csdn.net/in_clude/article/details/53146981
计算机器效果图
项目下载链接:http://download.csdn.net/detail/in_clude/9681337
代码如下
package yhz;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Main {
public static void main(String args[]){
final Show show=new Show();
show.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
super.mousePressed(e);
int tx=e.getY()-show.mDivHeight/2;
int ty=e.getX();
if(tx>show.mDivision){
show.mSelectX=(tx-show.mDivision)/show.mDivHeight;
show.mSelectY=ty/show.mDivWidth;
}
show.repaint();
}
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
super.mouseReleased(e);
show.mSelectX=-1;
show.mSelectY=-1;
show.repaint();
}
});
}
}
package yhz;
import java.awt.*;
import javax.swing.*;
public class Show extends JFrame {
public int mDivision; //按钮与显示的分界线
public int mDivWidth; //每个小格的宽
public int mDivHeight; //每个小格的高
public int[] mDivX = new int[10]; //存每个小格左上角的x坐标
public int[] mDivY = new int[10]; //存每个小格左上角的y坐标
public int mSelectX;
public int mSelectY;
public char [][] mSign = {{'C','<','(',')'},{'1','2','3','+'},{'4','5','6','-'},{'7','8','9','×'},{'.','0','=','÷'}};
public Deal mDeal = new Deal();
public Show(){
setTitle("小智的计算器");
setSize(90*3,160*3);
this.getContentPane().add(new MyPanel());
setVisible(true);
setResizable(false);
setLocation(400,100);
mSelectX=-1;
mSelectY=-1;
}
public class MyPanel extends JPanel{
private int flag=0;
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
/**
* 存储位置
*/
if(flag==0){
mDivision=this.getWidth()*9/16-30;
for(int i=0;i<6;i++){
mDivX[i]=mDivision+(this.getHeight()-mDivision)*i/5;
}
for(int i=0;i<5;i++){
mDivY[i]=this.getWidth()*i/4;
}
mDivHeight=(this.getHeight()-mDivision)/5; //5行
mDivWidth=this.getWidth()/4; //4列
flag=1;
}
/**
* 下面开始绘图
*/
//背景
for(int i=0;i<mDivision;i++){
Color myColor = new Color(255,200,i/2);
g.setColor(myColor);
g.drawLine(0, i, this.getWidth(), i);
}
for(int i=mDivision;i<this.getHeight();i++){
Color myColor = new Color(250-i/3,200-i/3,i/3);
g.setColor(myColor);
g.drawLine(0, i, this.getWidth(), i);
}
//按键效果
if(mSelectX!=-1&&mSelectY!=-1)
{
mDeal.Change(mSign[mSelectX][mSelectY]);
for(int i=mDivX[mSelectX];i<=mDivX[mSelectX]+mDivHeight;i++){
Color myColor = new Color(255,200,0);
g.setColor(myColor);
g.drawLine( mDivY[mSelectY], i, mDivY[mSelectY]+mDivWidth,i);
}
}
g.setColor(Color.white);
//网格
for(int i=0;i<5;i++){
g.drawLine(0, mDivX[i], this.getWidth(), mDivX[i]);
}
for(int i=1;i<=4;i++){
g.drawLine(mDivY[i], mDivision, mDivY[i], this.getHeight());
}
//绘字
for(int i=0;i<5;i++){
for(int j=0;j<4;j++){
g.drawString(String.valueOf(mSign[i][j]), mDivY[j]+mDivWidth/2-2, mDivX[i]+mDivHeight/2+5); //-2 +5是根据显示进行的微调
}
}
Font font = new Font("Arial", Font.PLAIN, 29);
g.setFont(font);
if(mDeal.mText==""){
g.drawString(mDeal.mAns, this.getWidth()-this.getFontMetrics(font).stringWidth(mDeal.mAns)-5, mDivision*2/3);
}
else
g.drawString(mDeal.mText, this.getWidth()-this.getFontMetrics(font).stringWidth(mDeal.mText)-5, mDivision*2/3);
Font font1 = new Font("Arial", Font.PLAIN, 16);
g.setFont(font1);
String str = new String();
for(int i=0;i<mDeal.mDetailPos;i++){
str+=mDeal.mTextDetail[i];
}
g.drawString(str, this.getWidth()-this.getFontMetrics(font1).stringWidth(str), mDivision/3);
}
}
}
package yhz;
import java.util.Stack;
public class Deal {
public String mText = new String();
public String[] mTextDetail = new String[100];//用数组方便后缀表达式那儿放入栈中
public int mDetailPos;
public String mAns = new String();
private int mLeftBracketNum;
private String[] mSuffix =new String[105];
private int mSuffixPos;
private Stack mTemp =new Stack();
public Deal(){
mLeftBracketNum=0;
mDetailPos=0;
mAns="0";
mText="";
}
public void Change(char c){
mAns="0";
if(c<='9'&&c>='0')
{ if(mDetailPos>0){
if(mTextDetail[mDetailPos-1].equals(")")==false)
mText+=c;
}
else
mText+=c;
}
else if(c=='+'||c=='-'||c=='×'||c=='÷'){
if(mText!=""){
if(mText.substring(mText.length()-1, mText.length()).equals("."))//确保末尾不能有小数点
{
mText=mText.substring(0, mText.length()-1);
}
mTextDetail[mDetailPos++]=mText;
String temp = new String();
temp = "";
temp+=c;
mTextDetail[mDetailPos++]=temp;
mText="";
}
else if(mTextDetail[mDetailPos-1].equals("(")==true){
}
else if(mTextDetail[mDetailPos-1].equals(")")==true){
String temp = new String();
temp = "";
temp+=c;
mTextDetail[mDetailPos++]=temp;
}
else if(mTextDetail[mDetailPos-1].equals(")")==false){
String temp = new String();
temp ="";
temp+=c;
mTextDetail[mDetailPos-1]=temp;
}
if(c=='+'||c=='-')
if(mLeftBracketNum==0){
Calculate();
}
}
else if(c=='C'){
mLeftBracketNum=0;
mText="";
for(int i=0;i<mDetailPos;i++){
mTextDetail[i]="";
}
mDetailPos=0;
mAns="0";
}
else if(c=='<'){
if(mText!=""){
if(mText.length()==1) mText="";
else
mText=mText.substring(0, mText.length()-1);
}
}
else if(c=='='){
if(mText!="")
mTextDetail[mDetailPos++]=mText;
for(int i=mLeftBracketNum;i>0;i--)//补全括号
{
mTextDetail[mDetailPos++]=")";
}
mTextDetail[mDetailPos++]="=";
Calculate();
for(int i=0;i<mDetailPos;i++){
mTextDetail[i]="";
}
mDetailPos=0;
mText="";
}
else if(c=='.'){
if(mText!=""){
if(mText.contains(".")==false){
mText+=c;
}
}
}
else if(c=='('){
if(mDetailPos==0){
mTextDetail[mDetailPos++]="(";
mLeftBracketNum++;
}
else if(mTextDetail[mDetailPos-1].equals("+")==true||
mTextDetail[mDetailPos-1].equals("-")==true||
mTextDetail[mDetailPos-1].equals("×")==true||
mTextDetail[mDetailPos-1].equals("÷")==true){
mTextDetail[mDetailPos++]="(";
mLeftBracketNum++;
}
}
else if(c==')'){
if(mLeftBracketNum>0){
if(mText!=""){
mTextDetail[mDetailPos++]=mText;
mTextDetail[mDetailPos++]=")";
mLeftBracketNum--;
mText="";
}
}
}
}
/**
* 中缀转后缀
*/
public void toSuffix(){
for(int i=0;i<mDetailPos-1;i++)//-1是因为式子包含了最后的 = + -
{
if(mTextDetail[i].equals("+")==true||
mTextDetail[i].equals("-")==true){
while( mTemp.empty()==false&&
(mTemp.peek().equals("+")==true||
mTemp.peek().equals("-")==true||
mTemp.peek().equals("×")==true||
mTemp.peek().equals("÷")==true) ){
mSuffix[mSuffixPos++]=(String) mTemp.peek();
mTemp.pop();
}
mTemp.push(mTextDetail[i]);
}
else if(mTextDetail[i].equals("×")==true||
mTextDetail[i].equals("÷")==true){
while( mTemp.empty()==false&&
(mTemp.peek().equals("×")==true||
mTemp.peek().equals("÷")==true)){
mSuffix[mSuffixPos++]=(String) mTemp.peek();
mTemp.pop();
}
mTemp.push(mTextDetail[i]);
}
else if(mTextDetail[i].equals("(")==true){
mTemp.push(mTextDetail[i]);
}
else if(mTextDetail[i].equals(")")==true){
while(mTemp.peek().equals("(")==false){
mSuffix[mSuffixPos++]=(String) mTemp.peek();
mTemp.pop();
}
mTemp.pop();
}
else {
mSuffix[mSuffixPos++]=mTextDetail[i];
}
}
while(mTemp.empty()==false){
mSuffix[mSuffixPos++]=(String) mTemp.peek();
mTemp.pop();
}
}
public void Calculate(){
mSuffixPos=0;
for(int i=0;i<100;i++){
mSuffix[i]="";
}
while(mTemp.empty()==false){
mTemp.pop();
}
toSuffix();
//输出测试
for(int i=0;i<mDetailPos;i++)
System.out.print(mTextDetail[i]+" ");
System.out.print("\n");
for(int i=0;i<mSuffixPos;i++){
System.out.print(mSuffix[i]+" ");
}
System.out.print("\n");
for(int i=0;i<mSuffixPos;i++){
if(mSuffix[i].equals("+")||mSuffix[i].equals("-")
||mSuffix[i].equals("×")||mSuffix[i].equals("÷")){
double b = Double.valueOf((String) mTemp.pop()).doubleValue();
double a = Double.valueOf((String) mTemp.pop()).doubleValue();
double c = 0;
if(mSuffix[i].equals("+")){
c = a + b;
}
if(mSuffix[i].equals("-")){
c = a - b;
}
if(mSuffix[i].equals("×")){
c = a * b;
}
if(mSuffix[i].equals("÷")){
c = a / b;
}
String str = Double.toString(c);
mTemp.push(str);
}
else {
mTemp.push(mSuffix[i]);
}
}
mAns = (String) mTemp.pop();
if(mAns.length()>16)//防止超出屏幕 如果超过了 改成指数形式输出更好
mAns = mAns.substring(0, 16);
}
}