Qt计算器开发(二):信号槽实现数学表达式合法性检查
表达式的合法性
由于我们的计算器不是单步计算的,所以我们能够一次性输入一个长表达式。然而假设用户输入的长表达式不合法的话,那么就会引发灾难。所以有必要对于用户的输入做一个限制。
一些限制举例:
比方,在输入了左括号以后那么接下来,不能输入运算符。此时运算符要是不可用的状态。在输入了右括号以后不能直接输入数字,此时数字键应该是不可用状态。等等此类的。
在这里我使用了信号与槽的方式来实现。点击不同的button,会发展出不同的信号。在这之后的事,点击button本身无需考虑,这也是信号槽的良好的设计理念造成的效果,符合面向对象的迪米特原则。
实现部分
常量
首先我们先定义五个常量:
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函数是特殊函数,无需实现部分。
然后在乘法button的槽函数中:
void MainWindow::on_btnMuti_clicked()
{
QString s = ui->lineEdit->text();
ui->lineEdit->setText(s+"*");
emit whichBtn(OPERA);
}
上面的ui->lineEdit就是我们计算器的屏幕控件。上面的s就是屏幕上已有的表达式了,点击乘号*button那么表达式后面多一个乘号*。然后发射一个信号whichBtn(OPERA).其它button类似。
然后怎样处理信号呢?
这里我在主窗体类的头文件中又声明了几个槽函数:
void enableDigit(int type);
void enableOp(int type);
void enableLeft(int type);
void enableRight(int type);
void enableEqual(int type);
用来实现button可用与否的实现,比方第一个是运算符可用与否,它的实现代码:
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写法,之前版本号的语法也兼容,只是不太鼓舞。由于太不安全了。很多错误仅仅有执行时才发现。由于原来的写法信号和槽都被转换为字符串了,那么我写错了信号或槽函数的名称是相同能够编译通过的,仅仅有执行时才干检測出来。而新语法则能保证在编译期间就检查出错误来。
右括号的处理
另外值得一提的是:右括号的可用性与其它button不同,它仅仅于左括号相关,而且一定要与左括号数目同样才合法。所以我在主窗体类里声明了一个整型变量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。
相同的在我们点击了一个左括号后,在槽函数voidMainWindow::on_btnLeft_clicked()中须要对lefts进行加一操作。而当我们点击了一个右括号后须要在槽函数voidMainWindow::on_btnRight_clicked()中对lefts进行减一操作。
================= 本 项 目 文 章 及 源 码 链 接===============
|== Qt计算器开发(一):后缀表达式实现完整数学表达式的计算 ==|
|== Qt计算器开发(二):信号槽实现数学表达式合法性检查 ==|
|== Qt计算器开发(三):执行效果及项目总结 ==|
|== Qt计算器源代码下载(免积分) ==|
|== Qt计算器GitHub托管地址(代码会不定期更新,敬请关注) ==|
=======================================================
Qt计算器开发(二):信号槽实现数学表达式合法性检查的更多相关文章
- Qt计算器开发(三):执行效果及项目总结
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/guodongxiaren/article/details/26046543 执行效果 project ...
- Qt开发之信号槽机制
一.信号槽机制原理 1.如何声明信号槽 Qt头文件中一段的简化版: class Example: public QObject { Q_OBJECT signals: void customSigna ...
- VS2008 Qt Designer 中自定义信号槽
一.Qt Designer自定义槽函数 发现:在VS2008 +Qt4.7 中打开ui文件,所用的英文QT Designer工具,没有转到槽函数的功能,不如QtCreator自带的QtDesigne ...
- QT学习之路---信号槽
#include<QApplication> #include<QPushButton> int main(int argc,char *argv[]) { QApplicat ...
- Qt不同类之间信号槽连接
1.类必须继承QObject. #ifndef TESTA_H #define TESTA_H #include <QObject> class TestA : public QObjec ...
- Qt学习记录--02 Qt的信号槽机制介绍(含Qt5与Qt4的差异对比)
一 闲谈: 熟悉Window下编程的小伙伴们,对其消息机制并不陌生, 话说:一切皆消息.它可以很方便实现不同窗体之间的通信,然而MFC库将很多底层的消息都屏蔽了,尽管使用户更加方便.简易地处理消息,但 ...
- Qt自定义信号槽的使用浅析+实例
1. Qt中自定义信号槽的使用 Qt框架提供的信号槽在某些特定场景下是无法满足我们的项目需求的,因此我们还设计自己需要的的信号和槽,使用connect()对自定义的信号槽进行连接. 如果想要使用自定义 ...
- 用ISO C++实现自己的信号槽(Qt另类学习)
qtc++objectsignalclassstring 目录(?)[-] Qt信号与槽 引入元对象系统 建立信号槽链接 信号的激活 槽的调用 全家福 零零散散写在后面 Q_OBJECT Conn ...
- Qt 学习之路:深入 Qt5 信号槽新语法
在前面的章节(信号槽和自定义信号槽)中,我们详细介绍了有关 Qt 5 的信号槽新语法.由于这次改动很大,许多以前看起来不是问题的问题接踵而来,因此,我们用单独的一章重新介绍一些 Qt 5 的信号槽新语 ...
随机推荐
- struts2 与 OGNL 表达式,jsp中 利用ognl 在valuestack中取值
在Struts2中,一个请求在终于到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是 ...
- Delphi实现窗口一直在桌面工作区内显示(重写WM_WINDOWPOSCHANGING消息)
有的时候我们要实现一个悬浮窗口,并使该窗口一直显示在桌面的工作区内.即整个窗口要一直显示在屏幕上,不能超出屏幕的上下左右边缘.此功能的实现也不难,我们需要自己写代码来响应窗口的WM_WINDOWPOS ...
- [Android学习笔记]Canvas的使用
Canvas文档 http://developer.android.com/training/index.html 在绘制view时候,重写onDraw(canvas)方法,可能需要在canvas上绘 ...
- Linux下一个简单的日志系统的设计及其C代码实现
1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回 ...
- MVVM Light须要注意的10个问题
MVVM Light须要注意的10个问题 从使用XAML技术基础開始(实际上并非非常久曾经).我便关注MVVM(Model – View – ViewModel)模式.偶然接触到MVVM Light不 ...
- Android中的跨进程通信方法实例及特点分析(二):ContentProvider
1.ContentProvider简单介绍 在Android中有些数据(如通讯录.音频.视频文件等)是要供非常多应用程序使用的.为了更好地对外提供数据.Android系统给我们提供了Content P ...
- hdu5171(矩阵快速幂)
传送门:GTY's birthday gift 题意:GTY的朋友ZZF的生日要来了,GTY问他的基友送什么礼物比较好,他的一个基友说送一个可重集吧!于是GTY找到了一个可重集S,GTY能使用神犇魔法 ...
- hdu4223(dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4223 由于n范围较小,完全可暴力... #include <cstdio> #includ ...
- Visual Prolog 的 Web 专家系统 (8)
GENI核心 -- 推理引擎(2)流量控制 1.阐述fail."!"而回溯 与其他语言相比,,Prolog最大的特点.这是回溯机制. 回溯机制,还有的主要手段2个月,首先,通过使用 ...
- PHP_SELF、 SCRIPT_NAME、 REQUEST_URI差别
$_SERVER[PHP_SELF], $_SERVER[SCRIPT_NAME], $_SERVER['REQUEST_URI'] 在使用方法上是很相似的,他们返回的都是与当前正在使用的页面地址有关 ...