表达式的合法性
因为我们的计算器不是单步计算的,所以我们可以一次性输入一个长表达式。然而如果用户输入的长表达式不合法的话,那么就会引发灾难。所以有必要对于用户的输入做一个限制。
一些限制举例:
比如,在输入了左括号以后那么接下来,不能输入运算符。此时运算符要是不可用的状态。在输入了右括号以后不能直接输入数字,此时数字键应该是不可用状态。等等此类的。
在这里我使用了信号与槽的方式来实现。点击不同的按钮,会发展出不同的信号。在这之后的事,点击按钮本身无需考虑,这也是信号槽的良好的设计理念造成的效果,符合面向对象的迪米特原则。
实现部分
常量
首先我们先定义五个常量:
const int INIT = 0;const int DIGIT = 1;const int OPERA = 2;const int LEFT = 3;const int RIGHT = 4;第一个常量表示初始化,这里也把它作为按键信号,可理解为特殊的按键,因为在最开始的时候,我们不能输入运算符,右括号,所以初始化时运算符,右括号为不可用状态。
信号与槽
主窗口的头文件里声明一句:
signals: void whichBtn(int type);了解Qt的都知道,信号signal函数是特殊函数,无需实现部分。
然后在乘法按钮的槽函数中:
void MainWindow::on_btnMuti_clicked(){ QString s = ui->lineEdit->text(); ui->lineEdit->setText(s+"*"); emit whichBtn(OPERA);}
上面的ui->lineEdit就是我们计算器的屏幕控件。上面的s就是屏幕上已有的表达式了,点击乘号*按钮那么表达式后面多一个乘号*。然后发射一个信号whichBtn(OPERA).其他按钮类似。
然后如何处理信号呢?
这里我在主窗口类的头文件里又声明了几个槽函数:
void enableDigit(int type); void enableOp(int type); void enableLeft(int type); void enableRight(int type); void enableEqual(int type);用来实现按钮可用与否的实现,比如第一个是运算符可用与否,它的实现代码:
void MainWindow::enableOp(int type){ bool enable = false; switch(type) { case DIGIT:enable = true; break; case INIT: case OPERA: case LEFT:enable = false; break; default:return; } ui->btnMuti->setEnabled(enable);//乘 ui->btnDivi->setEnabled(enable);//除 ui->btnAdd->setEnabled(enable);//加 ui->btnSub->setEnabled(enable);//减}
连接
最后呢,我们要连接啦。
connect(this,&MainWindow::whichBtn,&MainWindow::enableOp); connect(this,&MainWindow::whichBtn,&MainWindow::enableLeft); connect(this,&MainWindow::whichBtn,&MainWindow::enableEqual); connect(this,&MainWindow::whichBtn,&MainWindow::enableRight); connect(this,&MainWindow::whichBtn,&MainWindow::enableDigit);
我这里用的是Qt5的新版connect写法,之前版本的语法也兼容,不过不太鼓励。因为太不安全了。许多错误只有运行时才发现。因为原来的写法信号和槽都被转换为字符串了,那么我写错了信号或槽函数的名称是同样可以编译通过的,只有运行时才能检测出来。而新语法则能保证在编译期间就检查出错误来。
右括号的处理
另外值得一提的是:右括号的可用性与其他按钮不同,它只于左括号相关,并且一定要与左括号数目相同才合法。所以我在主窗口类里声明了一个整型变量lefts用于保存左括号的数目。
在右括号可用性的槽函数中:
void MainWindow::enableRight(int type){ bool enable = false; switch(type) { case INIT: case OPERA: break; case LEFT:enable = true; case RIGHT: case DIGIT: if(lefts) enable = true; break; default:return; } ui->btnRight->setEnabled(enable);}需要判断 lefts是否为零,如果不为零那么右括号可用,enable设为true。 同样的在我们点击了一个左括号后,在槽函数 void MainWindow :: on_btnLeft_clicked ()中需要对 lefts进行加一操作。而当我们点击了一个右括号后需要在槽函数 void MainWindow :: on_btnRight_clicked ()中对 lefts进行减一操作。
================= 本 项 目 文 章 及 源 码 链 接===============
|== ==| |== ==| |== ==| |== ==| |== ==| =======================================================