一、项目展示
计算器
二、UI界面实现与美化
1、UI界面布局
将两个文本输入框设置为只读模式,并靠右对齐
2、UI界面的美化
右键窗体选择更改样式表
*{
border:none;
background-color: rgb(234, 234, 234);
}
//其中 * 表示给所有的对象设置样式,其样式编写在 * 之后的花括号之中,border 设置为 none 表示边框为 none 则表示不需要边框,background-color 表示设置对应的背景色,用 rgb 色进行设置。
QPushButton{
background-color: rgb(255, 255, 255);
font:bold 11pt '微软雅黑';
}
//接着我们可以设置对应的 按钮样式,例如设置 QPushButton 的背景色以及对应的字体大小、是否加粗以及字体,可以使用以下样式
QPushButton#add,#subtraction,#division,#multiplication{
background-color: rgb(56, 208, 203);
}
//此时设置样式则需要先指定某个类型的组件,随后使用 # 在末尾街上控件名称,随后逗号分隔即可指定某个控件设置样式。
此时运行程序,我们发现鼠标移动到某个按钮上时没有任何反应,若想使按钮有反应则需要对应的设置 hover 时按钮的样式,hover 则是指对应的鼠标悬浮上去后,按钮发生的改变,设置这个样式很简单,只需要指定某个类型的控件后,在其后使用一个冒号 :hover 即可指定一个样式,例如:
QPushButton:hover{
background-color: rgb(221, 221, 221);
border:1px solid rgb(185, 185, 185);
}
QPushButton#add:hover,#subtraction:hover,#division:hover,#multiplication:hover{
background-color: rgb(221, 221, 221);
border:1px solid rgb(185, 185, 185);
}
//但此时我们发现,设置过指定控件的样式例如加减乘除并没有移动上去后发生样式改变,这时需要再针对这些控件设置一下 hover 样式
三、项目代码
完整代码如下:
#include "widget.h"
#include "ui_widget.h"
#include <QStack>
const int maxn=110;
char priority[7][7]={
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'}, // 此行"("=")"表示左右括号相遇,括号内运算已完成
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='} // "=" 表示整个表达式求值完毕
}; // "0"表示不可能出现这种情况 ( 语法错误 )
//Precede 用于判断运算符栈栈顶运算符 a1 与读入运算符 a2 之间的优先关系函数
char Procede(char a,char b){ // 建立 pre[][] 到 运算符间的映射关系
int i,j;
switch(a){
case'+':i=0;break;
case'-':i=1;break;
case'*':i=2;break;
case'/':i=3;break;
case'(':i=4;break;
case')':i=5;break;
case'#':i=6;break; // # 是表达式的结束符
}
switch(b){
case'+':j=0;break;
case'-':j=1;break;
case'*':j=2;break;
case'/':j=3;break;
case'(':j=4;break;
case')':j=5;break;
case'#':j=6;break;
}
return priority[i][j];
}
int Operate(int m,int n,char x){
if(x=='+')
return m+n;
if(x=='-')
return n-m;
if(x=='*')
return m*n;
if(x=='/')
return n/m;
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_btn7_clicked()
{
expression += "7";
ui->show->setText(expression);
}
void Widget::on_btn8_clicked()
{
expression += "8";
ui->show->setText(expression);
}
void Widget::on_btn9_clicked()
{
expression += "9";
ui->show->setText(expression);
}
void Widget::on_btncheng_clicked()
{
expression += "*";
ui->show->setText(expression);
}
void Widget::on_btn4_clicked()
{
expression += "4";
ui->show->setText(expression);
}
void Widget::on_btn5_clicked()
{
expression += "5";
ui->show->setText(expression);
}
void Widget::on_btn6_clicked()
{
expression += "6";
ui->show->setText(expression);
}
void Widget::on_btnchu_clicked()
{
expression += "/";
ui->show->setText(expression);
}
void Widget::on_btn1_clicked()
{
expression += "1";
ui->show->setText(expression);
}
void Widget::on_btn2_clicked()
{
expression += "2";
ui->show->setText(expression);
}
void Widget::on_btn3_clicked()
{
expression += "3";
ui->show->setText(expression);
}
void Widget::on_btn0_clicked()
{
expression += "0";
ui->show->setText(expression);
}
void Widget::on_btnjia_clicked()
{
expression += "+";
ui->show->setText(expression);
}
void Widget::on_btnjian_clicked()
{
expression += "-";
ui->show->setText(expression);
}
void Widget::on_btnresult_clicked()
{
QStack <int> OPND; // Operand stack
QStack <char> OPTR; // Operator stack
OPTR.push('#');//
char ss[2]="#";//尾部有\0
char s[maxn];
char path[50];
QString str = expression;
QByteArray ba = str.toLocal8Bit();
memcpy(s,ba.data(),ba.size()+1);//加1是为了最后的终结符,否则转换回来的时候不知道什么时候截止
QString str2;
str2 = QString::fromLocal8Bit(s);
strcat(s,ss);// 运算式尾部加 "#"--结束运算符
char c=s[0];
int k=1;
while(c!='#'||OPTR.top()!='#'){ //表达式未读完或者运算未完
int y=0;
if(c>='0'&&c<='9'){
while(c>='0'&&c<='9'){ // 读入连续的数字
y=y*10+(c-'0');
c=s[k++];
}
OPND.push(y); // 把读进的数字入数字栈
}
else{
switch(Procede(OPTR.top(),c))
{
case'<': //栈顶元素优先权低
OPTR.push(c);
c=s[k++];
break;
case'=':
OPTR.pop(); // 脱括号
c=s[k++]; // 读入下一个字符
break;
case'>': //退栈并将运算结果入栈
char x=OPTR.top();OPTR.pop();
int m=OPND.top();OPND.pop();
int n=OPND.top();OPND.pop();
OPND.push(Operate(m,n,x));
break;
}
}
}
ui->res->setText(QString::number(OPND.top()));
}
void Widget::on_btnclear_clicked()
{
ui->res->clear();
ui->show->clear();
}
上述代码中按钮的槽函数如下:
void Widget::on_btnchu_clicked()
{
expression += "/";
ui->show->setText(expression);
}
将所有按钮槽函数都实现后,实现计算功能要获取文本框的内容复制网上的计算器案例,将计算器案例复制到等于按钮的槽函数。将下面代码复制到widget.c中。
const int maxn=110;
char priority[7][7]={
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'}, // 此行"("=")"表示左右括号相遇,括号内运算已完成
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='} // "=" 表示整个表达式求值完毕
}; // "0"表示不可能出现这种情况 ( 语法错误 )
//Precede 用于判断运算符栈栈顶运算符 a1 与读入运算符 a2 之间的优先关系函数
char Procede(char a,char b){ // 建立 pre[][] 到 运算符间的映射关系
int i,j;
switch(a){
case'+':i=0;break;
case'-':i=1;break;
case'*':i=2;break;
case'/':i=3;break;
case'(':i=4;break;
case')':i=5;break;
case'#':i=6;break;
}
switch(b){
case'+':j=0;break;
case'-':j=1;break;
case'*':j=2;break;
case'/':j=3;break;
case'(':j=4;break;
case')':j=5;break;
case'#':j=6;break;
}
return priority[i][j];
}
int Operate(int m,int n,char x){
if(x=='+')
return m+n;
if(x=='-')
return n-m;
if(x=='*')
return m*n;
if(x=='/')
return n/m;
}
并且将头文件加入到widget.c中
#include <QStack>