嵌入式Qt 实现用户界面与业务逻辑分离

一.基本程序框架一般包含

二.框架的基本设计原则

三.用户界面与业务逻辑的交互

 

 四.代码实现计算器用户界面与业务逻辑

ICalculator.h

#ifndef _ICALCULATOR_H_
#define _ICALCULATOR_H_#include <QString>class ICalculator
{
public:virtual bool expression(const QString& exp) = 0;virtual QString result() = 0;
};#endif

QCalculator.h

#ifndef _QCALCULATOR_H_
#define _QCALCULATOR_H_#include "QCalculatorUI.h"
#include "QCalculatorDec.h"class QCalculator
{
protected:QCalculatorUI* m_ui;QCalculatorDec m_cal;QCalculator();bool construct();
public:static QCalculator* NewInstance();void show();~QCalculator();
};#endif // QCALCULATOR_H

QCalculator.cpp

#include "QCalculator.h"QCalculator::QCalculator()
{
}bool QCalculator::construct()
{m_ui = QCalculatorUI::NewInstance();if( m_ui != NULL ){m_ui->setCalculator(&m_cal);}return (m_ui != NULL);
}QCalculator* QCalculator::NewInstance()
{QCalculator* ret = new QCalculator();if( (ret == NULL) || !ret->construct() ){delete ret;ret = NULL;}return ret;
}void QCalculator::show()
{m_ui->show();
}QCalculator::~QCalculator()
{delete m_ui;
}

QCalculatorDec.h

#ifndef _CALCULATORCORE_H_
#define _CALCULATORCORE_H_#include <QString>
#include <QStack>
#include <QQueue>#include "ICalculator.h"class QCalculatorDec : public ICalculator
{
protected:QString m_exp;QString m_result;bool isDigitOrDot(QChar c);bool isSymbol(QChar c);bool isSign(QChar c);bool isNumber(QString s);bool isOperator(QString s);bool isLeft(QString s);bool isRight(QString s);int priority(QString s);bool match(QQueue<QString>& exp);QString calculate(QQueue<QString>& exp);QString calculate(QString l, QString op, QString r);bool transform(QQueue<QString>& exp, QQueue<QString>& output);QQueue<QString> split(const QString& exp);
public:QCalculatorDec();~QCalculatorDec();bool expression(const QString& exp);QString expression();QString result();
};#endif

 QCalculatorDec.cpp

#include "QCalculatorDec.h"QCalculatorDec::QCalculatorDec()
{m_exp = "";m_result = "";
}QCalculatorDec::~QCalculatorDec()
{}bool QCalculatorDec::isDigitOrDot(QChar c)
{return (('0' <= c) && (c <= '9')) || (c == '.');
}bool QCalculatorDec::isSymbol(QChar c)
{return isOperator(c) || (c == '(') || (c == ')');
}bool QCalculatorDec::isSign(QChar c)
{return (c == '+') || (c == '-');
}bool QCalculatorDec::isNumber(QString s)
{bool ret = false;s.toDouble(&ret);return ret;
}bool QCalculatorDec::isOperator(QString s)
{return (s == "+") || (s == "-") || (s == "*") || (s == "/");
}bool QCalculatorDec::isLeft(QString s)
{return (s == "(");
}bool QCalculatorDec::isRight(QString s)
{return (s == ")");
}int QCalculatorDec::priority(QString s)
{int ret = 0;if( (s == "+") || (s == "-") ){ret = 1;}if( (s == "*") || (s == "/") ){ret = 2;}return ret;
}bool QCalculatorDec::expression(const QString& exp)
{bool ret = false;QQueue<QString> spExp = split(exp);QQueue<QString> postExp;m_exp = exp;if( transform(spExp, postExp) ){m_result = calculate(postExp);ret = (m_result != "Error");}else{m_result = "Error";}return ret;
}QString QCalculatorDec::result()
{return m_result;
}QQueue<QString> QCalculatorDec::split(const QString& exp)
{QQueue<QString> ret;QString num = "";QString pre = "";for(int i=0; i<exp.length(); i++){if( isDigitOrDot(exp[i]) ){num += exp[i];pre = exp[i];}else if( isSymbol(exp[i]) ){if( !num.isEmpty() ){ret.enqueue(num);num.clear();}if( isSign(exp[i]) && ((pre == "") || (pre == "(") || isOperator(pre)) ){num += exp[i];}else{ret.enqueue(exp[i]);}pre = exp[i];}}if( !num.isEmpty() ){ret.enqueue(num);}return ret;
}bool QCalculatorDec::match(QQueue<QString>& exp)
{bool ret = true;int len = exp.length();QStack<QString> stack;for(int i=0; i<len; i++){if( isLeft(exp[i]) ){stack.push(exp[i]);}else if( isRight(exp[i]) ){if( !stack.isEmpty() && isLeft(stack.top()) ){stack.pop();}else{ret = false;break;}}}return ret && stack.isEmpty();
}bool QCalculatorDec::transform(QQueue<QString>& exp, QQueue<QString>& output)
{bool ret = match(exp);QStack<QString> stack;output.clear();while( ret && !exp.isEmpty() ){QString e = exp.dequeue();if( isNumber(e) ){output.enqueue(e);}else if( isOperator(e) ){while( !stack.isEmpty() && (priority(e) <= priority(stack.top())) ){output.enqueue(stack.pop());}stack.push(e);}else if( isLeft(e) ){stack.push(e);}else if( isRight(e) ){while( !stack.isEmpty() && !isLeft(stack.top()) ){output.enqueue(stack.pop());}if( !stack.isEmpty() ){stack.pop();}}else{ret = false;}}while( !stack.isEmpty() ){output.enqueue(stack.pop());}if( !ret ){output.clear();}return ret;
}QString QCalculatorDec::calculate(QString l, QString op, QString r)
{QString ret = "Error";if( isNumber(l) && isNumber(r) ){double lp = l.toDouble();double rp = r.toDouble();if( op == "+" ){ret.sprintf("%f", lp + rp);}else if( op == "-" ){ret.sprintf("%f", lp - rp);}else if( op == "*" ){ret.sprintf("%f", lp * rp);}else if( op == "/" ){const double P = 0.000000000000001;if( (-P < rp) && (rp < P) ){ret = "Error";}else{ret.sprintf("%f", lp / rp);}}else{ret = "Error";}}return ret;
}QString QCalculatorDec::calculate(QQueue<QString>& exp)
{QString ret = "Error";QStack<QString> stack;while( !exp.isEmpty() ){QString e = exp.dequeue();if( isNumber(e) ){stack.push(e);}else if( isOperator(e) ){QString rp = !stack.isEmpty() ? stack.pop() : "";QString lp = !stack.isEmpty() ? stack.pop() : "";QString result = calculate(lp, e, rp);if( result != "Error" ){stack.push(result);}else{break;}}else{break;}}if( exp.isEmpty() && (stack.size() == 1) && isNumber(stack.top()) ){ret = stack.pop();}return ret;
}

QCalculatorUI.h

#ifndef _QCALCULATORUI_H_
#define _QCALCULATORUI_H_#include <QWidget>
#include <QLineEdit>
#include <QPushButton>#include "ICalculator.h"class QCalculatorUI : public QWidget
{Q_OBJECT
private:QLineEdit* m_edit;QPushButton* m_buttons[20];ICalculator* m_cal;QCalculatorUI();bool construct();
private slots:void onButtonClicked();
public:static QCalculatorUI* NewInstance();void show();void setCalculator(ICalculator* cal);ICalculator* getCalculator();~QCalculatorUI();
};#endif

QCalculatorUI.cpp

#include "QCalculatorUI.h"
#include <QDebug>QCalculatorUI::QCalculatorUI() : QWidget(NULL, Qt::WindowCloseButtonHint)
{m_cal = NULL;
}bool QCalculatorUI::construct()
{bool ret = true;const char* btnText[20] ={"7", "8", "9", "+", "(","4", "5", "6", "-", ")","1", "2", "3", "*", "<-","0", ".", "=", "/", "C",};m_edit = new QLineEdit(this);if( m_edit != NULL ){m_edit->move(10, 10);m_edit->resize(240, 30);m_edit->setReadOnly(true);m_edit->setAlignment(Qt::AlignRight);}else{ret = false;}for(int i=0; (i<4) && ret; i++){for(int j=0; (j<5) && ret; j++){m_buttons[i*5 + j] = new QPushButton(this);if( m_buttons[i*5 + j] != NULL ){m_buttons[i*5 + j]->resize(40, 40);m_buttons[i*5 + j]->move(10 + (10 + 40)*j, 50 + (10 + 40)*i);m_buttons[i*5 + j]->setText(btnText[i*5 + j]);connect(m_buttons[i*5 + j], SIGNAL(clicked()), this, SLOT(onButtonClicked()));}else{ret = false;}}}return ret;
}QCalculatorUI* QCalculatorUI::NewInstance()
{QCalculatorUI* ret = new QCalculatorUI();if( (ret == NULL) || !ret->construct() ){delete ret;ret = NULL;}return ret;
}void QCalculatorUI::show()
{QWidget::show();setFixedSize(width(), height());
}void QCalculatorUI::onButtonClicked()
{QPushButton* btn = dynamic_cast<QPushButton*>(sender());if( btn != NULL ){QString clickText = btn->text();if( clickText == "<-" ){QString text = m_edit->text();if( text.length() > 0 ){text.remove(text.length()-1, 1);m_edit->setText(text);}}else if( clickText == "C" ){m_edit->setText("");}else if( clickText == "=" ){if( m_cal != NULL ){m_cal->expression(m_edit->text());m_edit->setText(m_cal->result());}}else{m_edit->setText(m_edit->text() + clickText);}}
}void QCalculatorUI::setCalculator(ICalculator* cal)
{m_cal = cal;
}ICalculator* QCalculatorUI::getCalculator()
{return m_cal;
}QCalculatorUI::~QCalculatorUI()
{}

main.cpp

#include <QApplication>#include "QCalculator.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);QCalculator* cal = QCalculator::NewInstance();int ret = -1;if( cal != NULL ){cal->show();ret = a.exec();delete cal;}return ret;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/703849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人脸2D和3D道具SDK解决方案提供商

人脸识别和增强现实技术成为了许多企业和开发者关注的焦点&#xff0c;为了满足市场对高质量、易于集成的人脸识别SDK的需求&#xff0c;美摄科技推出了一系列领先的人脸2D/3D道具SDK解决方案。 一、产品特点 高精度识别&#xff1a;美摄科技的人脸识别技术采用深度学习算法&…

C++——二叉搜索树

二叉搜索树 二叉搜索树&#xff1a; 又为搜索二叉树&#xff0c;一般具有以下的性质 若它的左子树不为空&#xff0c;则左子树上所有的节点的值都小于父亲节点若它的右子树不为空&#xff0c;则右子树上所有的节点的值都大于父亲节点它的左右子树也都为二叉搜索树 二叉搜索树…

漏电保护继电器 导轨安装 零序电流互感器配套使用DJ-ZB1 DH-30L

系列型号&#xff1a; DJ-ZB1剩余&#xff08;漏电&#xff09;电流保护继电器 DJ-ZB2剩余&#xff08;漏电&#xff09;电流保护继电器 DJ-ZB3剩余&#xff08;漏电&#xff09;电流保护继电器 DJ-ZB4剩余&#xff08;漏电&#xff09;电流保护继电器 DJ-ZB5剩余&#xff08;漏…

pytorch保存张量为图片

这里用到的是torchvision中的save_image。 废话不多说&#xff0c;直接来代码&#xff1a; import torch from torchvision.utils import save_image B, C, H, W 64, 3, 32, 32 input_tensor torch.randn(B, C, H, W) save_image(input_tensor, "hh.png", nrow8)…

Shell脚本入门:从基础到实践,轻松掌握Shell编程

前言 在数字化和信息化的今天&#xff0c;计算机和操作系统成为了我们生活和工作中不可或缺的一部分。对于经常使用计算机的人来说&#xff0c;Shell&#xff08;命令行界面&#xff09;是一个非常重要的工具。而Shell脚本&#xff0c;则是对命令行操作的一种自动化和批量化处…

stm32:timer模块,如何计数,计数模块很简单,但是需要注意分频的设置,分频设置为7199,

首先看配置项 计数模块很简单&#xff0c;但是需要注意分频的设置&#xff0c;分频设置为7199&#xff0c; 然后计数寄存器里的值65535作为默认值&#xff0c;也可以在matlab里修改 下图为配置项目&#xff1a; 下图为matlab模型&#xff1a; 下图为运行结果&#xff1a; 计…

python(ch2)

可变长编码和不可变长编码 可变长编码是指不同字符使用不同数量的字节进行编码。例如&#xff0c;UTF-8 编码中&#xff0c;ASCII 字符使用 1 个字节编码&#xff0c;而其他语言的字符使用 2 个或更多字节编码。 不可变长编码是指所有字符都使用相同数量的字节进行编码。例如…

甲氧基 PEG4 二苯并环辛烯,mPEG4 DBCO,可以与多种基团发生反应

甲氧基四聚乙二醇二苯并环辛烯&#xff0c;甲氧基 PEG4 二苯并环辛烯&#xff0c;mPEG4 DBCO&#xff0c;DBCO mPEG4&#xff0c;m-PEG4-DBCO&#xff0c;mPEG4-DBCO&#xff0c;可以与多种基团发生反应 您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;甲氧基四聚乙…

【Python_Zebra斑马打印机编程学习笔记(三)】解决ZPL指令无法显示中文的问题

解决ZPL指令无法显示中文的问题 解决ZPL指令无法显示中文的问题前言一、问题描述二、字符集、码表文件、字库文件1、字符集2、码表文件3、字库文件 三、两种设置中文字体的方式1、通过设置字符集、码表文件、字库文件改变默认字体2、通过^CF指令设置标准字体名称改变默认字体 解…

Linux命令行常用命令

初识shell shell是系统的用户界面&#xff0c;提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。实际上shell是一个命令解释器&#xff0c;它解释用户输入的命令并且把用户的意图传达给内核。&#xff08;可以理解为用户与内核之间的翻译官…

如何本地部署LightPicture结合cpolar内网穿透打造个人云图床

文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进&#xff0c;功能也越来越多&#xff0c;而手机…

还不知道随身WiFi这个蓝海市场怎么做?这个一定要看!适合30-40岁轻资产小生意

有没有发现你身边的人最近都在失业&#xff1f;无论是国企的、事业编的、又或者是民营企业的都在欠薪或者失业&#xff0c;看来经济寒潮是真的来了。虽然经济大环境不好&#xff0c;但是仍然涌现出了物联网、人工智能、大数据等新兴的蓝海市场。可是很多创投圈的朋友都表示&…

15:00面试,15:06就出来了,问的问题过于变态了。。。

我从一家小公司转投到另一家公司&#xff0c;期待着新的工作环境和机会。然而&#xff0c;新公司的加班文化让我有些始料未及。虽然薪资相对较高&#xff0c;但长时间的工作和缺乏休息使我身心俱疲。 就在我逐渐适应这种高强度的工作节奏时&#xff0c;公司突然宣布了一则令人…

蓝桥杯-最小砝码

知识点&#xff1a;本题主要考察任何一个物体都可以用 3进制表示。 #include <iostream> #include<cmath> using namespace std; //知识点:任何一个物体都可以用 3进制表示 int main() { int n; cin >> n; int sum 0; for (int i 0;; i)…

vue2实现无感刷新token

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 &#x1f4d8; 引言&#xff1a; &#x1f4…

【Vue3】学习watch监视:深入了解Vue3响应式系统的核心功能(上)

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

携程token算法分析

声明 本文以教学为基准、本文提供的可操作性不得用于任何商业用途和违法违规场景。 本人对任何原因在使用本人中提供的代码和策略时可能对用户自己或他人造成的任何形式的损失和伤害不承担责任。 如有侵权,请联系我进行删除。 这里只是我分析的分析过程,以及一些重要点的记录…

[云原生] k8s中kubectl陈述式资源管理

一、管理k8s核心资源的两种基本方法 陈述式资源管理方法 --主要依赖命令行工具kubectl进行管理 优点 可以满足90%以上的使用场景 对资源的增、删、查操作比较容易 缺点 命令冗长&#xff0c;复杂&#xff0c;难以记忆 特定场景下&#xff0c;无法实现管理需求 对资源的修改…

每日汇评:英镑可能走高,而1.2650支撑位保持不变

英镑/美元上周收于正值区域&#xff1b; 1.2650是该货币对的关键近期支撑位&#xff1b; 如果市场情绪恶化&#xff0c;该货币对的上涨空间可能仍然有限&#xff1b; 英镑/美元利用围绕美元的广泛抛售压力&#xff0c;自 1 月初以来首次录得周涨幅。 周一早盘该货币对稳定在 1.…

Premiere企业发展历程公司历史回顾视频制作pr时间线模板

企业发展历程公司历史回顾视频制作PR时间线模板mogrt。 项目特点&#xff1a;色彩控件&#xff0c;适用于任何字体&#xff0c;包含视频帮助&#xff0c;适用于Premiere Pro 2021及以上版本。 更多PR资源下载&#xff1a;https://prmuban.com/37916.html