环境
Qt 5.4.2
功能
QWidget 实现简易计算器
源码
1.CalculatorApp.h
#define DEF_MAXCOUNT 13
//运算符
#define DEF_SIGNADD "+"
#define DEF_SIGNSUB "-"
#define DEF_SIGNMUL "×"
#define DEF_SIGNDIV "/"
#define DEF_SIGNEQU "="
//数学函数
#define DEF_MATHRATE "%" //百分比
#define DEF_MATHFRAC "1/" //1/x
#define DEF_MATHSQR "sqr" //X²
#define DEF_MATHROOT "√" //√x
enum ENUM_SEGTYPE{
ENUM_SEGNTYPE_NUL=1000,
ENUM_SEGNTYPE_VALUE, //数值
ENUM_SEGNTYPE_SIGN, //符号
};
typedef struct {
ENUM_SEGTYPE eSegType; //数据类型: 数值/符号
double dbValue; //数据
QString strExpress; //表达式
}TagSegInfo;
/** 标准计算器 **/
class CalculatorApp : public QWidget
{
Q_OBJECT
private:
void printfExpress(); //显式表达式
QString formatDouble(double dbValue);
void calculErrorEvent(bool isError);
void digiButtonClick(QString digiVal); //数字键盘按下
void mathButtonClick(QString funType); //数学函数按下
void mathFunctionCal(QString funType); //数学函数计算
void signButtonClick(QString sign); //数学符号按下
int calculatExpress(); //计算表达式
private slots:
void on_pushButton_0_clicked();
void on_pushButton_1_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void on_pushButton_5_clicked();
void on_pushButton_6_clicked();
void on_pushButton_7_clicked();
void on_pushButton_8_clicked();
void on_pushButton_9_clicked();
void on_pushButton_neg_clicked();
void on_pushButton_point_clicked();
void on_pushButton_rate_clicked();
void on_pushButton_fract_clicked();
void on_pushButton_square_clicked();
void on_pushButton_root_clicked();
void on_pushButton_add_clicked();
void on_pushButton_sub_clicked();
void on_pushButton_mul_clicked();
void on_pushButton_div_clicked();
void on_pushButton_equal_clicked();
void on_pushButton_CE_clicked();
void on_pushButton_C_clicked();
void on_pushButton_back_clicked();
private:
QList<TagSegInfo> tagSegList;
bool bIsAppendDot;
bool bIsCalcError; //表达式错误
bool bIsDigitPres; //符号件按下后时候有数字键按下?
private:
Ui::CalculatorApp *ui;
};
#endif // CALCULATORAPP_H
2.CalculatorApp.cpp
CalculatorApp::CalculatorApp(QWidget *parent)
: QWidget(parent)
, ui(new Ui::CalculatorApp)
{
ui->setupUi(this);
bIsAppendDot = true;
bIsCalcError = false;
bIsDigitPres = false;
}
void CalculatorApp::printfExpress()
{
QString strValue = "";
ui->label_express->setText("");
for(int i=0; i<tagSegList.size() ;i++)
{
strValue += tagSegList.at(i).strExpress;
}
ui->label_express->setText(strValue);
}
void CalculatorApp::calculErrorEvent(bool isError)
{
bIsCalcError = isError;
ui->pushButton_rate->setEnabled(!isError);
ui->pushButton_fract->setEnabled(!isError);
ui->pushButton_square->setEnabled(!isError);
ui->pushButton_root->setEnabled(!isError);
ui->pushButton_div->setEnabled(!isError);
ui->pushButton_mul->setEnabled(!isError);
ui->pushButton_sub->setEnabled(!isError);
ui->pushButton_add->setEnabled(!isError);
ui->pushButton_point->setEnabled(!isError);
ui->pushButton_neg->setEnabled(!isError);
if(!isError) //init
{
tagSegList.clear();
ui->label_express->setText("");
ui->label_result->setText("0");
bIsAppendDot = true;
bIsDigitPres = false;
}
}
void CalculatorApp::on_pushButton_0_clicked() { digiButtonClick("0");}
void CalculatorApp::on_pushButton_1_clicked() { digiButtonClick("1");}
void CalculatorApp::on_pushButton_2_clicked() { digiButtonClick("2");}
void CalculatorApp::on_pushButton_3_clicked() { digiButtonClick("3");}
void CalculatorApp::on_pushButton_4_clicked() { digiButtonClick("4");}
void CalculatorApp::on_pushButton_5_clicked() { digiButtonClick("5");}
void CalculatorApp::on_pushButton_6_clicked() { digiButtonClick("6");}
void CalculatorApp::on_pushButton_7_clicked() { digiButtonClick("7");}
void CalculatorApp::on_pushButton_8_clicked() { digiButtonClick("8");}
void CalculatorApp::on_pushButton_9_clicked() { digiButtonClick("9");}
void CalculatorApp::on_pushButton_rate_clicked() {mathButtonClick(DEF_MATHRATE);}
void CalculatorApp::on_pushButton_fract_clicked() {mathButtonClick(DEF_MATHFRAC);}
void CalculatorApp::on_pushButton_square_clicked(){mathButtonClick(DEF_MATHSQR); }
void CalculatorApp::on_pushButton_root_clicked() {mathButtonClick(DEF_MATHROOT);}
void CalculatorApp::on_pushButton_add_clicked(){ signButtonClick("+");}
void CalculatorApp::on_pushButton_sub_clicked(){ signButtonClick("-");}
void CalculatorApp::on_pushButton_mul_clicked(){ signButtonClick("×");}
void CalculatorApp::on_pushButton_div_clicked(){ signButtonClick("/");}
void CalculatorApp::on_pushButton_equal_clicked()
{
if(bIsCalcError) { calculErrorEvent(false); return ; }
signButtonClick("=");
}
void CalculatorApp::on_pushButton_neg_clicked() {
double dbValue = ui->label_result->text().toDouble();
dbValue = 0 - dbValue;
ui->label_result->setText(formatDouble(dbValue));
if((0 < tagSegList.size()) && (ENUM_SEGNTYPE_VALUE == tagSegList.at(tagSegList.size()-1).eSegType))
{
TagSegInfo tagSegInfo;
tagSegInfo.eSegType = ENUM_SEGNTYPE_VALUE;
tagSegInfo.dbValue = dbValue;
tagSegInfo.strExpress ="negate("+tagSegList.at(tagSegList.size()-1).strExpress+")";
tagSegList.replace(tagSegList.size()-1,tagSegInfo);
printfExpress();
}
if((0 < tagSegList.size()) && (DEF_SIGNEQU == tagSegList.at(tagSegList.size()-1).strExpress))
{
tagSegList.clear();
printfExpress();
}
}
void CalculatorApp::on_pushButton_point_clicked(){
if(DEF_MAXCOUNT <= ui->label_result->text().count()) { return; }
bIsDigitPres = true;
if((tagSegList.size() > 0) && (DEF_SIGNEQU == tagSegList.at(tagSegList.size()-1).strExpress))
{
tagSegList.clear();
printfExpress();
}
if(!bIsAppendDot) { ui->label_result->setText("0."); }
else{ ui->label_result->setText(ui->label_result->text()+"."); }
}
void CalculatorApp::on_pushButton_CE_clicked()
{
if(bIsCalcError) { calculErrorEvent(false); }
if((tagSegList.size() > 0) && (DEF_SIGNEQU == tagSegList.at(tagSegList.size()-1).strExpress))
{
tagSegList.clear();
printfExpress();
}
bIsDigitPres = false;
ui->label_result->setText("0");
}
void CalculatorApp::on_pushButton_C_clicked()
{
if(bIsCalcError) { calculErrorEvent(false); }
tagSegList.clear();
ui->label_result->setText("0");
ui->label_express->setText("");
bIsAppendDot = true;
bIsCalcError = false;
bIsDigitPres = false;
}
void CalculatorApp::on_pushButton_back_clicked()
{
if(bIsCalcError) { calculErrorEvent(false); }
if((tagSegList.size() > 0) && (ENUM_SEGNTYPE_VALUE == tagSegList.at(tagSegList.size()-1).eSegType))
{ return;}
if((tagSegList.size() > 0) && (ENUM_SEGNTYPE_SIGN == tagSegList.at(tagSegList.size()-1).eSegType))
{
if(ENUM_SEGNTYPE_SIGN == tagSegList.at(tagSegList.size()-1).eSegType)
{
tagSegList.clear();
printfExpress();
bIsDigitPres = false;
return;
}
if(!bIsDigitPres) { return; }
}
if(1 < ui->label_result->text().count())
{ ui->label_result->setText(ui->label_result->text().mid(0,ui->label_result->text().count()-1));}
else{ ui->label_result->setText("0"); bIsDigitPres = false;}
}
//Double value 小数点位数处理
QString CalculatorApp::formatDouble(double dbValue)
{
int ndecimal = DEF_MAXCOUNT -1-QString::number(dbValue,'f',0).count();
QString strResult = QString::number(dbValue,'f',ndecimal);
while('0' == strResult.at(strResult.count()-1))
{
strResult = strResult.mid(0,strResult.count()-1);
}
if('.' == strResult.at(strResult.count()-1))
{
strResult = strResult.mid(0,strResult.count()-1);
}
if(strResult.count() > (1+DEF_MAXCOUNT))
{
calculErrorEvent(true);
strResult = "溢出";
}
return strResult;
}
//数字按键
void CalculatorApp::digiButtonClick(QString digiVal)
{
if(DEF_MAXCOUNT < ui->label_result->text().count()) { return; }
if(bIsCalcError) { calculErrorEvent(false);}
bIsAppendDot = true;
if((0 < tagSegList.size()) && (ENUM_SEGNTYPE_VALUE == tagSegList.at(tagSegList.size()-1).eSegType))
{
tagSegList.removeLast();
printfExpress();
ui->label_result->setText(digiVal);
bIsDigitPres = true;
return;
}
if((0 < tagSegList.size()) && (ENUM_SEGNTYPE_SIGN == tagSegList.at(tagSegList.size()-1).eSegType) &&(!bIsDigitPres))
{
if(DEF_SIGNEQU == tagSegList.at(tagSegList.size()-1).strExpress) { tagSegList.clear(); printfExpress();}
ui->label_result->setText(digiVal);
bIsDigitPres = true;
return;
}
if((0 >= tagSegList.size()) && (!bIsDigitPres))
{
ui->label_result->setText(digiVal);
bIsDigitPres = true;
return;
}
if("0" == ui->label_result->text()) { ui->label_result->setText(digiVal); }
else { ui->label_result->setText(ui->label_result->text()+digiVal); }
bIsDigitPres = true;
}
//数学函数
void CalculatorApp::mathButtonClick(QString funType)
{
double dbValue = ui->label_result->text().toDouble();
//Error
if((DEF_MATHFRAC == funType) && (0 == dbValue)) {
calculErrorEvent(true);
ui->label_express->setText(ui->label_express->text()+"1/(0)");
ui->label_result->setText("除数不能为0");
return;
}
if((DEF_MATHROOT == funType) && (0 > dbValue)) {
calculErrorEvent(true);
ui->label_express->setText("√("+ ui->label_result->text()+")");
ui->label_result->setText("无效输入");
return;
}
//无效计算
if((DEF_MATHRATE == funType) && (0 >= tagSegList.size()))
{
tagSegList.clear();
ui->label_result->setText("0");
ui->label_express->setText("");
return;
}
//清空
if((0 < tagSegList.size()) && (DEF_SIGNEQU == tagSegList.at(tagSegList.size()-1).strExpress))
{
tagSegList.clear();
}
mathFunctionCal(funType);
}
//数学函数
void CalculatorApp::mathFunctionCal(QString funType)
{
TagSegInfo tagSegInfo;
tagSegInfo.eSegType = ENUM_SEGNTYPE_VALUE;
tagSegInfo.dbValue = ui->label_result->text().toDouble();
tagSegInfo.strExpress =funType;
bIsAppendDot = false;
bIsDigitPres = true;
if(DEF_MATHRATE == funType)
{
tagSegInfo.dbValue = tagSegInfo.dbValue / (double)100;
}else if(DEF_MATHFRAC == funType)
{
tagSegInfo.dbValue = (double)1 / tagSegInfo.dbValue ;
}else if(DEF_MATHSQR == funType)
{
tagSegInfo.dbValue *= tagSegInfo.dbValue ;
}else if(DEF_MATHROOT == funType)
{
tagSegInfo.dbValue = qSqrt(tagSegInfo.dbValue );
}
if((0 >= tagSegList.size()) || ((0 < tagSegList.size()) && (ENUM_SEGNTYPE_SIGN == tagSegList.at(tagSegList.size()-1).eSegType)))
{
if(DEF_MATHRATE == tagSegInfo.strExpress){ tagSegInfo.strExpress = formatDouble(tagSegInfo.dbValue); }
else { tagSegInfo.strExpress = tagSegInfo.strExpress+"("+ui->label_result->text()+")"; }
ui->label_result->setText(formatDouble(tagSegInfo.dbValue));
tagSegList.append(tagSegInfo);
printfExpress();
return;
}
if((0 < tagSegList.size()) && (ENUM_SEGNTYPE_VALUE == tagSegList.at(tagSegList.size()-1).eSegType))
{
if(DEF_MATHRATE == tagSegInfo.strExpress){tagSegInfo.strExpress = formatDouble(tagSegInfo.dbValue);}
else{tagSegInfo.strExpress = tagSegInfo.strExpress+"("+tagSegList.at(tagSegList.size()-1).strExpress+")";}
ui->label_result->setText(formatDouble(tagSegInfo.dbValue));
tagSegList.replace(tagSegList.size()-1,tagSegInfo);
printfExpress();
return;
}
}
//运算符
void CalculatorApp::signButtonClick(QString sign)
{
bIsAppendDot = false;
TagSegInfo tagSegInfo1;
TagSegInfo tagSegInfo2;
tagSegInfo1.eSegType = ENUM_SEGNTYPE_VALUE;
tagSegInfo1.dbValue = ui->label_result->text().toDouble();
tagSegInfo1.strExpress = ui->label_result->text();
tagSegInfo2.eSegType = ENUM_SEGNTYPE_SIGN;
tagSegInfo2.dbValue = 0;
tagSegInfo2.strExpress = sign;
if(0 >= tagSegList.size())
{
tagSegList.append(tagSegInfo1);
tagSegList.append(tagSegInfo2);
printfExpress();
bIsDigitPres = false;
return;
}
if(ENUM_SEGNTYPE_VALUE == tagSegList.at(tagSegList.size()-1).eSegType)
{
tagSegList.append(tagSegInfo2);
if(1 >= tagSegList.size()) {
printfExpress();
bIsDigitPres = false;
return;
}
}
if(ENUM_SEGNTYPE_SIGN == tagSegList.at(tagSegList.size()-1).eSegType)
{
if((DEF_SIGNEQU == sign) && (DEF_SIGNEQU == tagSegList.at(tagSegList.size()-1).strExpress) && (2 >= tagSegList.size()))
{ return; }
if((DEF_SIGNEQU != sign) && (DEF_SIGNEQU == tagSegList.at(tagSegList.size()-1).strExpress) && (2 >= tagSegList.size()))
{
tagSegList.replace(tagSegList.size()-1,tagSegInfo2);
printfExpress();
bIsDigitPres = false;
return;
}
if((DEF_SIGNEQU != sign) && (DEF_SIGNEQU == tagSegList.at(tagSegList.size()-1).strExpress))
{
tagSegList.removeLast();
tagSegList.removeLast();
tagSegList.replace(tagSegList.size()-1,tagSegInfo2);
printfExpress();
bIsDigitPres = false;
return;
}
if((DEF_SIGNEQU != sign) && (!bIsDigitPres))
{
tagSegList.replace(tagSegList.size()-1,tagSegInfo2);
printfExpress();
bIsDigitPres = false;
return;
}
}
if(2 >= tagSegList.size())
{
tagSegList.append(tagSegInfo1);
tagSegList.append(tagSegInfo2);
}
if(DEF_SIGNEQU == sign) { printfExpress(); }
if(-1 == calculatExpress()) { return; }
if(DEF_SIGNEQU != sign) { tagSegList.removeAt(1); tagSegList.removeAt(1); printfExpress(); }
ui->label_result->setText(tagSegList.at(0).strExpress);
bIsDigitPres = false;
}
//运算符
int CalculatorApp::calculatExpress()
{
if(2 > tagSegList.size()) {return -1; }
double dbValue = 0;
if(DEF_SIGNEQU == tagSegList.at(1).strExpress)
{
dbValue = tagSegList.at(0).dbValue;
}
if(3 > tagSegList.size()) {return -1; }
if(DEF_SIGNADD == tagSegList.at(1).strExpress)
{
dbValue = tagSegList.at(0).dbValue + tagSegList.at(2).dbValue;
}else if(DEF_SIGNSUB == tagSegList.at(1).strExpress)
{
dbValue = tagSegList.at(0).dbValue - tagSegList.at(2).dbValue;
}else if(DEF_SIGNMUL == tagSegList.at(1).strExpress)
{
dbValue = tagSegList.at(0).dbValue * tagSegList.at(2).dbValue;
}else if(DEF_SIGNDIV == tagSegList.at(1).strExpress)
{
if(0 == tagSegList.at(2).dbValue)
{
calculErrorEvent(true);
printfExpress();
ui->label_result->setText("除数不能为0");
return -1;
}
dbValue = tagSegList.at(0).dbValue / tagSegList.at(2).dbValue;
}
TagSegInfo tagSegInfo;
tagSegInfo.eSegType = ENUM_SEGNTYPE_VALUE;
tagSegInfo.dbValue = dbValue;
tagSegInfo.strExpress = formatDouble(dbValue);
tagSegList.replace(0,tagSegInfo);
return 0;
}
3.CalculatorApp.ui
部分QSS
QStackedWidget{
background-color: rgb(255, 255, 255);
}
QPushButton{
font: 18pt "宋体";
border:0px;
background-color: rgb(239, 242, 247);
}
QPushButton:hover{
border:0px;
background-color: rgb(222, 222, 222);
}
QPushButton:pressed{
border:2px solid rgb(170,170,170);
background-color: rgb(203, 203, 203);
}