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


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

    二.框架的基本设计原则

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

     

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

    ICalculator.h

    1. #ifndef _ICALCULATOR_H_
    2. #define _ICALCULATOR_H_
    3. #include
    4. class ICalculator
    5. {
    6. public:
    7. virtual bool expression(const QString& exp) = 0;
    8. virtual QString result() = 0;
    9. };
    10. #endif

    QCalculator.h

    1. #ifndef _QCALCULATOR_H_
    2. #define _QCALCULATOR_H_
    3. #include "QCalculatorUI.h"
    4. #include "QCalculatorDec.h"
    5. class QCalculator
    6. {
    7. protected:
    8. QCalculatorUI* m_ui;
    9. QCalculatorDec m_cal;
    10. QCalculator();
    11. bool construct();
    12. public:
    13. static QCalculator* NewInstance();
    14. void show();
    15. ~QCalculator();
    16. };
    17. #endif // QCALCULATOR_H

    QCalculator.cpp

    1. #include "QCalculator.h"
    2. QCalculator::QCalculator()
    3. {
    4. }
    5. bool QCalculator::construct()
    6. {
    7. m_ui = QCalculatorUI::NewInstance();
    8. if( m_ui != NULL )
    9. {
    10. m_ui->setCalculator(&m_cal);
    11. }
    12. return (m_ui != NULL);
    13. }
    14. QCalculator* QCalculator::NewInstance()
    15. {
    16. QCalculator* ret = new QCalculator();
    17. if( (ret == NULL) || !ret->construct() )
    18. {
    19. delete ret;
    20. ret = NULL;
    21. }
    22. return ret;
    23. }
    24. void QCalculator::show()
    25. {
    26. m_ui->show();
    27. }
    28. QCalculator::~QCalculator()
    29. {
    30. delete m_ui;
    31. }

    QCalculatorDec.h

    1. #ifndef _CALCULATORCORE_H_
    2. #define _CALCULATORCORE_H_
    3. #include
    4. #include
    5. #include
    6. #include "ICalculator.h"
    7. class QCalculatorDec : public ICalculator
    8. {
    9. protected:
    10. QString m_exp;
    11. QString m_result;
    12. bool isDigitOrDot(QChar c);
    13. bool isSymbol(QChar c);
    14. bool isSign(QChar c);
    15. bool isNumber(QString s);
    16. bool isOperator(QString s);
    17. bool isLeft(QString s);
    18. bool isRight(QString s);
    19. int priority(QString s);
    20. bool match(QQueue& exp);
    21. QString calculate(QQueue& exp);
    22. QString calculate(QString l, QString op, QString r);
    23. bool transform(QQueue& exp, QQueue& output);
    24. QQueue split(const QString& exp);
    25. public:
    26. QCalculatorDec();
    27. ~QCalculatorDec();
    28. bool expression(const QString& exp);
    29. QString expression();
    30. QString result();
    31. };
    32. #endif

     QCalculatorDec.cpp

    1. #include "QCalculatorDec.h"
    2. QCalculatorDec::QCalculatorDec()
    3. {
    4. m_exp = "";
    5. m_result = "";
    6. }
    7. QCalculatorDec::~QCalculatorDec()
    8. {
    9. }
    10. bool QCalculatorDec::isDigitOrDot(QChar c)
    11. {
    12. return (('0' <= c) && (c <= '9')) || (c == '.');
    13. }
    14. bool QCalculatorDec::isSymbol(QChar c)
    15. {
    16. return isOperator(c) || (c == '(') || (c == ')');
    17. }
    18. bool QCalculatorDec::isSign(QChar c)
    19. {
    20. return (c == '+') || (c == '-');
    21. }
    22. bool QCalculatorDec::isNumber(QString s)
    23. {
    24. bool ret = false;
    25. s.toDouble(&ret);
    26. return ret;
    27. }
    28. bool QCalculatorDec::isOperator(QString s)
    29. {
    30. return (s == "+") || (s == "-") || (s == "*") || (s == "/");
    31. }
    32. bool QCalculatorDec::isLeft(QString s)
    33. {
    34. return (s == "(");
    35. }
    36. bool QCalculatorDec::isRight(QString s)
    37. {
    38. return (s == ")");
    39. }
    40. int QCalculatorDec::priority(QString s)
    41. {
    42. int ret = 0;
    43. if( (s == "+") || (s == "-") )
    44. {
    45. ret = 1;
    46. }
    47. if( (s == "*") || (s == "/") )
    48. {
    49. ret = 2;
    50. }
    51. return ret;
    52. }
    53. bool QCalculatorDec::expression(const QString& exp)
    54. {
    55. bool ret = false;
    56. QQueue<QString> spExp = split(exp);
    57. QQueue<QString> postExp;
    58. m_exp = exp;
    59. if( transform(spExp, postExp) )
    60. {
    61. m_result = calculate(postExp);
    62. ret = (m_result != "Error");
    63. }
    64. else
    65. {
    66. m_result = "Error";
    67. }
    68. return ret;
    69. }
    70. QString QCalculatorDec::result()
    71. {
    72. return m_result;
    73. }
    74. QQueue<QString> QCalculatorDec::split(const QString& exp)
    75. {
    76. QQueue<QString> ret;
    77. QString num = "";
    78. QString pre = "";
    79. for(int i=0; i<exp.length(); i++)
    80. {
    81. if( isDigitOrDot(exp[i]) )
    82. {
    83. num += exp[i];
    84. pre = exp[i];
    85. }
    86. else if( isSymbol(exp[i]) )
    87. {
    88. if( !num.isEmpty() )
    89. {
    90. ret.enqueue(num);
    91. num.clear();
    92. }
    93. if( isSign(exp[i]) && ((pre == "") || (pre == "(") || isOperator(pre)) )
    94. {
    95. num += exp[i];
    96. }
    97. else
    98. {
    99. ret.enqueue(exp[i]);
    100. }
    101. pre = exp[i];
    102. }
    103. }
    104. if( !num.isEmpty() )
    105. {
    106. ret.enqueue(num);
    107. }
    108. return ret;
    109. }
    110. bool QCalculatorDec::match(QQueue<QString>& exp)
    111. {
    112. bool ret = true;
    113. int len = exp.length();
    114. QStack<QString> stack;
    115. for(int i=0; i<len; i++)
    116. {
    117. if( isLeft(exp[i]) )
    118. {
    119. stack.push(exp[i]);
    120. }
    121. else if( isRight(exp[i]) )
    122. {
    123. if( !stack.isEmpty() && isLeft(stack.top()) )
    124. {
    125. stack.pop();
    126. }
    127. else
    128. {
    129. ret = false;
    130. break;
    131. }
    132. }
    133. }
    134. return ret && stack.isEmpty();
    135. }
    136. bool QCalculatorDec::transform(QQueue<QString>& exp, QQueue<QString>& output)
    137. {
    138. bool ret = match(exp);
    139. QStack<QString> stack;
    140. output.clear();
    141. while( ret && !exp.isEmpty() )
    142. {
    143. QString e = exp.dequeue();
    144. if( isNumber(e) )
    145. {
    146. output.enqueue(e);
    147. }
    148. else if( isOperator(e) )
    149. {
    150. while( !stack.isEmpty() && (priority(e) <= priority(stack.top())) )
    151. {
    152. output.enqueue(stack.pop());
    153. }
    154. stack.push(e);
    155. }
    156. else if( isLeft(e) )
    157. {
    158. stack.push(e);
    159. }
    160. else if( isRight(e) )
    161. {
    162. while( !stack.isEmpty() && !isLeft(stack.top()) )
    163. {
    164. output.enqueue(stack.pop());
    165. }
    166. if( !stack.isEmpty() )
    167. {
    168. stack.pop();
    169. }
    170. }
    171. else
    172. {
    173. ret = false;
    174. }
    175. }
    176. while( !stack.isEmpty() )
    177. {
    178. output.enqueue(stack.pop());
    179. }
    180. if( !ret )
    181. {
    182. output.clear();
    183. }
    184. return ret;
    185. }
    186. QString QCalculatorDec::calculate(QString l, QString op, QString r)
    187. {
    188. QString ret = "Error";
    189. if( isNumber(l) && isNumber(r) )
    190. {
    191. double lp = l.toDouble();
    192. double rp = r.toDouble();
    193. if( op == "+" )
    194. {
    195. ret.sprintf("%f", lp + rp);
    196. }
    197. else if( op == "-" )
    198. {
    199. ret.sprintf("%f", lp - rp);
    200. }
    201. else if( op == "*" )
    202. {
    203. ret.sprintf("%f", lp * rp);
    204. }
    205. else if( op == "/" )
    206. {
    207. const double P = 0.000000000000001;
    208. if( (-P < rp) && (rp < P) )
    209. {
    210. ret = "Error";
    211. }
    212. else
    213. {
    214. ret.sprintf("%f", lp / rp);
    215. }
    216. }
    217. else
    218. {
    219. ret = "Error";
    220. }
    221. }
    222. return ret;
    223. }
    224. QString QCalculatorDec::calculate(QQueue<QString>& exp)
    225. {
    226. QString ret = "Error";
    227. QStack<QString> stack;
    228. while( !exp.isEmpty() )
    229. {
    230. QString e = exp.dequeue();
    231. if( isNumber(e) )
    232. {
    233. stack.push(e);
    234. }
    235. else if( isOperator(e) )
    236. {
    237. QString rp = !stack.isEmpty() ? stack.pop() : "";
    238. QString lp = !stack.isEmpty() ? stack.pop() : "";
    239. QString result = calculate(lp, e, rp);
    240. if( result != "Error" )
    241. {
    242. stack.push(result);
    243. }
    244. else
    245. {
    246. break;
    247. }
    248. }
    249. else
    250. {
    251. break;
    252. }
    253. }
    254. if( exp.isEmpty() && (stack.size() == 1) && isNumber(stack.top()) )
    255. {
    256. ret = stack.pop();
    257. }
    258. return ret;
    259. }

    QCalculatorUI.h

    1. #ifndef _QCALCULATORUI_H_
    2. #define _QCALCULATORUI_H_
    3. #include
    4. #include
    5. #include
    6. #include "ICalculator.h"
    7. class QCalculatorUI : public QWidget
    8. {
    9. Q_OBJECT
    10. private:
    11. QLineEdit* m_edit;
    12. QPushButton* m_buttons[20];
    13. ICalculator* m_cal;
    14. QCalculatorUI();
    15. bool construct();
    16. private slots:
    17. void onButtonClicked();
    18. public:
    19. static QCalculatorUI* NewInstance();
    20. void show();
    21. void setCalculator(ICalculator* cal);
    22. ICalculator* getCalculator();
    23. ~QCalculatorUI();
    24. };
    25. #endif

    QCalculatorUI.cpp

    1. #include "QCalculatorUI.h"
    2. #include <QDebug>
    3. QCalculatorUI::QCalculatorUI() : QWidget(NULL, Qt::WindowCloseButtonHint)
    4. {
    5. m_cal = NULL;
    6. }
    7. bool QCalculatorUI::construct()
    8. {
    9. bool ret = true;
    10. const char* btnText[20] =
    11. {
    12. "7", "8", "9", "+", "(",
    13. "4", "5", "6", "-", ")",
    14. "1", "2", "3", "*", "<-",
    15. "0", ".", "=", "/", "C",
    16. };
    17. m_edit = new QLineEdit(this);
    18. if( m_edit != NULL )
    19. {
    20. m_edit->move(10, 10);
    21. m_edit->resize(240, 30);
    22. m_edit->setReadOnly(true);
    23. m_edit->setAlignment(Qt::AlignRight);
    24. }
    25. else
    26. {
    27. ret = false;
    28. }
    29. for(int i=0; (i<4) && ret; i++)
    30. {
    31. for(int j=0; (j<5) && ret; j++)
    32. {
    33. m_buttons[i*5 + j] = new QPushButton(this);
    34. if( m_buttons[i*5 + j] != NULL )
    35. {
    36. m_buttons[i*5 + j]->resize(40, 40);
    37. m_buttons[i*5 + j]->move(10 + (10 + 40)*j, 50 + (10 + 40)*i);
    38. m_buttons[i*5 + j]->setText(btnText[i*5 + j]);
    39. connect(m_buttons[i*5 + j], SIGNAL(clicked()), this, SLOT(onButtonClicked()));
    40. }
    41. else
    42. {
    43. ret = false;
    44. }
    45. }
    46. }
    47. return ret;
    48. }
    49. QCalculatorUI* QCalculatorUI::NewInstance()
    50. {
    51. QCalculatorUI* ret = new QCalculatorUI();
    52. if( (ret == NULL) || !ret->construct() )
    53. {
    54. delete ret;
    55. ret = NULL;
    56. }
    57. return ret;
    58. }
    59. void QCalculatorUI::show()
    60. {
    61. QWidget::show();
    62. setFixedSize(width(), height());
    63. }
    64. void QCalculatorUI::onButtonClicked()
    65. {
    66. QPushButton* btn = dynamic_cast<QPushButton*>(sender());
    67. if( btn != NULL )
    68. {
    69. QString clickText = btn->text();
    70. if( clickText == "<-" )
    71. {
    72. QString text = m_edit->text();
    73. if( text.length() > 0 )
    74. {
    75. text.remove(text.length()-1, 1);
    76. m_edit->setText(text);
    77. }
    78. }
    79. else if( clickText == "C" )
    80. {
    81. m_edit->setText("");
    82. }
    83. else if( clickText == "=" )
    84. {
    85. if( m_cal != NULL )
    86. {
    87. m_cal->expression(m_edit->text());
    88. m_edit->setText(m_cal->result());
    89. }
    90. }
    91. else
    92. {
    93. m_edit->setText(m_edit->text() + clickText);
    94. }
    95. }
    96. }
    97. void QCalculatorUI::setCalculator(ICalculator* cal)
    98. {
    99. m_cal = cal;
    100. }
    101. ICalculator* QCalculatorUI::getCalculator()
    102. {
    103. return m_cal;
    104. }
    105. QCalculatorUI::~QCalculatorUI()
    106. {
    107. }

    main.cpp

    1. #include
    2. #include "QCalculator.h"
    3. int main(int argc, char *argv[])
    4. {
    5. QApplication a(argc, argv);
    6. QCalculator* cal = QCalculator::NewInstance();
    7. int ret = -1;
    8. if( cal != NULL )
    9. {
    10. cal->show();
    11. ret = a.exec();
    12. delete cal;
    13. }
    14. return ret;
    15. }

  • 相关阅读:
    Android Jetpack学习系列——Room
    00后卷王的自述,我难道真的很卷?
    还不懂Java线程池实现原理,看这一篇文章就够了
    企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
    二、Flink SQL 调优汇总
    module内包含第三方aar包,完整打包上传maven的方法
    滚雪球学Java(09-2):Java中的关系运算符,你真的掌握了吗?
    L1-012 计算指数 C++
    keepalived实现nginx高可用
    03-基于Feign的远程调用,详解Feign的自定义配置和优化,创建Feign模块
  • 原文地址:https://blog.csdn.net/weixin_49303682/article/details/136282468