文章目录

  • 完整版
    • examdialog.h
    • examdialog.cpp
    • 运行结果
      • 单选未做完:
      • 多选未做完
      • 判断未做完
      • 满分情况
      • 非满分情况
  • 细节剖析
    • 相比于上一版增加的方法和实现
      • examdialog.h
      • examdialog.cpp
  • 知识点归类
    • 信号与槽完成提交功能
    • 判断“单/多选按——判断按钮”是否被选上了
    • 选中按钮是否包含答案
  • 下一篇预告

完整版

examdialog.h

#ifndef EXAMDIALOG_H
#define EXAMDIALOG_H
#include <QDialog>
#include <QTimer>
#include <QTextEdit>
#include <QLabel>
#include <QRadioButton>
#include <QCheckBox>
#include <QGridLayout>
#include <QButtonGroup>class ExamDialog : public QDialog
{Q_OBJECT
public:ExamDialog(QWidget* parent = 0);void initTimer();   //初始化计时器void initLayout();  //初始化布局管理器bool initTextEdit();//初始化文本编辑器void initButtons(); //初始化按钮及标签bool hasNoSelect(); //判断题目是否有未完成的
private:QTimer *m_timer;    //计时器int m_timeGo;       //考试已用时QTextEdit *m_textEdit;  //考试题库显示QLabel *m_titleLabels[10];  //题目标签QButtonGroup *m_btnGroups[9];   //单项按钮分组QRadioButton *m_radioBtns[32];  //单选题按钮QCheckBox *m_checkBtns[4];      //多选题按钮QRadioButton *m_radioA;         //判断题A选项QRadioButton *m_radioB;         //判断题B选项QGridLayout *m_layout;          //布局管理器QStringList m_answerList;       //存放答案的链表private slots:void freshTime();   //刷新考试时间void getScore();    //获取考试成绩
};#endif // EXAMDIALOG_H

examdialog.cpp


#include "examdialog.h"
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QApplication>
#include <QPushButton>ExamDialog::ExamDialog(QWidget* parent):QDialog(parent)
{//设置字体大小QFont font;font.setPointSize(12);setFont(font);//设置窗体背景颜色setPalette(QPalette(QColor(209,215,255)));setWindowTitle("考试已用时:0分0秒");setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); //基本对话框风格加上一个关闭按钮resize(800,900);// 调用初始化计时器initTimer();//初始化布局管理器initLayout();//初始化文本编辑器if(!initTextEdit()){QMessageBox::information(this,"提示","初始化题库数据文件失败!");//因为初始化失败,所以系统就直接退出(发送信号)。//第一个参数:多久来发送信号(0:立即退出)  第二个参数:想要那个对象相应槽方法(当前应用程序:QApp[应用程序的全局对象])  第三个参数:响应方法QTimer::singleShot(0,qApp,SLOT(quit()));//间隔0s,当前的应用程序执行退出操作}initButtons();show();
}void ExamDialog::initTimer()
{m_timeGo = 0;m_timer = new QTimer(this);m_timer->setInterval(1000);m_timer->start();connect(m_timer,SIGNAL(timeout()),this,SLOT(freshTime()));
}void ExamDialog::initLayout()
{m_layout = new QGridLayout(this);m_layout->setSpacing(10);   //设置控件间的间距m_layout->setMargin(10);    //设置窗体与控件间的间隙
}bool ExamDialog::initTextEdit()
{QString strLine;        //保存文件中读取到的一行数据QStringList strList;    //保存读取到的答案行QString fileName("exam.txt");QFile file(fileName);QTextStream stream(&file);stream.setCodec("UTF-8");if( file.open(QIODevice::ReadOnly | QIODevice::Text) ){m_textEdit = new QTextEdit(this);m_textEdit->setReadOnly(true);  //将文本设置为只读属性,不然现实的文本框居然还能够被修改。QString strText;    //用于保存显示到文本编辑器的数据int nLines = 0;while(!stream.atEnd()){//过滤首行if(nLines == 0){stream.readLine();nLines++;continue;}//过滤答案行(题目、ABCD、答案一共是6行)。一共有10个题。第十题是判断题需要特殊的处理。if( (nLines >= 6 && nLines <= 6 * 9 && (nLines % 6 == 0) )  /*选择题的答案*/|| (nLines == 6 * 9 + 4)/*判断题的答案行*/){//对于答案行的处理strLine = stream.readLine();    //先读取这一行strList = strLine.split(" ");   //对答案进行处理——以空格进行分割(eg:答案 A)m_answerList.append(strList.at(1));//把答案存放到答案链表里边 因为0:答案 1:A\b\c\dstrText += "\n";nLines++;continue;}//读取一行strText += stream.readLine();strText += "\n";nLines++;}//添加布局m_textEdit->setText(strText);m_layout->addWidget(m_textEdit,0,0,1,10);//窗口对象,行、列、行宽、列宽file.close();return true;}else{return false;}
}void ExamDialog::initButtons()
{//答案的文本QStringList strList = {"A","B","C","D"};//对十道题进行布局for(int i = 0; i <10; i++){//题目标签m_titleLabels[i] = new QLabel(this);m_titleLabels[i]->setText("第" + QString::number(i+1) + "题");//添加到布局管理器中 参一:添加的部件的对象  参二:第几行(因为文本编辑器在第0行,所以题目标签在第1行) 参三:第几列m_layout->addWidget(m_titleLabels[i],1,i);//判断题(也就是最后一题了——需要特殊处理的)if(i == 9){//单选m_radioA = new QRadioButton(this);//构造单选对象m_radioB = new QRadioButton(this);//构造单选对象//添加到布局里面(文本编辑器第0行、题目标签第1行) 正确地2行,错误第3行 判断题占据最后一列。m_radioA->setText("正确");m_radioB->setText("错误");m_layout->addWidget(m_radioA,2,9);  //正确:2行9列m_layout->addWidget(m_radioB,3,9);  //错误:3行9列//将单选进行分组,不加这个的话,就会整个单选框只能选择一个m_btnGroups[8] = new QButtonGroup(this);m_btnGroups[8]->addButton(m_radioA);m_btnGroups[8]->addButton(m_radioB);//判断题是最后一个溜了,当他构造完了之后直接就能退出了break;}if(i < 8) m_btnGroups[i] = new QButtonGroup(this);//选择题(4个按钮需要布局)for(int j = 0; j < 4; j++){if( i == 8){//第八题为:多项多选题。所以需要特殊处理m_checkBtns[j] = new QCheckBox(this);//构造多选对象m_checkBtns[j]->setText(strList.at(j)); //拿到 A、B、C、D这四个选项m_layout->addWidget(m_checkBtns[j],2+j,8);  //A、B、C、D各占第2、3、4、5行8第列}else{//单项选择题m_radioBtns[4 * i + j] = new QRadioButton(this);    //构造出所有的单选的按钮对象m_radioBtns[4 * i + j]->setText(strList.at(j));     //拿到 A、B、C、D这四个选项m_layout->addWidget(m_radioBtns[4 * i + j],2+j,i);  //A、B、C、D各占第2、3、4、5行0~7第列//将单选进行分组,不加这个的话,就会整个单选框只能选择一个m_btnGroups[i]->addButton(m_radioBtns[4 * i + j]);}}}//构造提交按钮的对象QPushButton *submitBtn = new QPushButton(this);submitBtn->setText("提交");submitBtn->setFixedSize(100,35);//适用槽函数来获取分数connect(submitBtn,SIGNAL(clicked(bool)),this,SLOT(getScore()));m_layout->addWidget(submitBtn,6,9); //设置提交按钮的位置
}//判断题目是否有未完成的
bool ExamDialog::hasNoSelect()
{int radioSelects = 0;//单选题的计数//通过按钮分组来判断,来检查按钮是否被选上了for(int i = 0; i < 8; i++){//如果有按钮选上了,计数+1if( m_btnGroups[i]->checkedButton() )radioSelects++;}//如果不足 8 说明有未完成的单选if(radioSelects != 8)return true;//对多选按钮进行判断——只要有选中了的就行int checkSelects = 0;for(int i = 0; i < 4; i++){if(m_checkBtns[i]->isChecked())checkSelects++;}//如果多选只有1个或者没有那么就选的不完全,即又为完成的选项if(checkSelects == 0 || checkSelects == 1)return true;//判断题——只有有一个选上了就okif(!m_radioA->isChecked() && !m_radioB->isChecked())return true;return false;
}void ExamDialog::getScore()
{if(hasNoSelect()){QMessageBox::information(this,"提示","您有未完成的题目,请完成考试!","是");return;}int scores = 0;//对10个题进行判断for(int i = 0; i < 10; i++){//单选题计分if( i < 8)//与链表中的答案进行对比,如果正确,则+10if(m_btnGroups[i]->checkedButton()->text() == m_answerList.at(i))scores += 10;//多项选择题计分if(i == 8){QString answer = m_answerList.at(i);bool hasA = false;bool hasB = false;bool hasC = false;bool hasD = false;//contains:是否包含指定的字符串//提取答案是否正确if( answer.contains("A") ) hasA = true;if( answer.contains("B") ) hasB = true;if( answer.contains("C") ) hasC = true;if( answer.contains("D") ) hasD = true;//提取选择的按钮是否选中。选中了返回true,未选中falsebool checkA = m_checkBtns[0]->checkState();bool checkB = m_checkBtns[1]->checkState();bool checkC = m_checkBtns[2]->checkState();bool checkD = m_checkBtns[3]->checkState();//因为多选要所有答案都对才记分,如果状态不一致那么跳过本次循环if( hasA != checkA) continue;if( hasB != checkB) continue;if( hasC != checkC) continue;if( hasD != checkD) continue;scores += 10;}//判断题计分if(i == 9){//选中项文本和答案文本进行对比if(m_btnGroups[8]->checkedButton()->text() == m_answerList.at(i))scores += 10;}}//如果分数太低,用户想再考一次的话。QString str = "您的分数是:" + QString::number(scores) + "分,是否重新考试?";int res = QMessageBox::information(this,"提示",str,QMessageBox::Yes | QMessageBox::No);if(res == QMessageBox::Yes)return;elseclose();
}void ExamDialog::freshTime()
{m_timeGo++;QString min = QString::number(m_timeGo / 60);QString sec = QString::number(m_timeGo % 60);setWindowTitle("考试已用时:" + min + "分" + sec + "秒");
}

运行结果

单选未做完:

多选未做完

判断未做完

满分情况

非满分情况

细节剖析

相比于上一版增加的方法和实现

examdialog.h

//examdialog.h新增加 方法
public:bool hasNoSelect(); //判断题目是否有未完成的private slots:void getScore();    //获取考试成绩

examdialog.cpp

//examdialog.cpp中的实现
//判断题目是否有未完成的
bool ExamDialog::hasNoSelect()
{int radioSelects = 0;//单选题的计数//通过按钮分组来判断,来检查按钮是否被选上了for(int i = 0; i < 8; i++){//如果有按钮选上了,计数+1if( m_btnGroups[i]->checkedButton() )radioSelects++;}//如果不足 8 说明有未完成的单选if(radioSelects != 8)return true;//对多选按钮进行判断——只要有选中了的就行int checkSelects = 0;for(int i = 0; i < 4; i++){if(m_checkBtns[i]->isChecked())checkSelects++;}//如果多选只有1个或者没有那么就选的不完全,即又为完成的选项if(checkSelects == 0 || checkSelects == 1)return true;//判断题——只有有一个选上了就okif(!m_radioA->isChecked() && !m_radioB->isChecked())return true;return false;
}void ExamDialog::getScore()
{if(hasNoSelect()){QMessageBox::information(this,"提示","您有未完成的题目,请完成考试!","是");return;}int scores = 0;//对10个题进行判断for(int i = 0; i < 10; i++){//单选题计分if( i < 8)//与链表中的答案进行对比,如果正确,则+10if(m_btnGroups[i]->checkedButton()->text() == m_answerList.at(i))scores += 10;//多项选择题计分if(i == 8){QString answer = m_answerList.at(i);bool hasA = false;bool hasB = false;bool hasC = false;bool hasD = false;//contains:是否包含指定的字符串//提取答案是否正确if( answer.contains("A") ) hasA = true;if( answer.contains("B") ) hasB = true;if( answer.contains("C") ) hasC = true;if( answer.contains("D") ) hasD = true;//提取选择的按钮是否选中。选中了返回true,未选中falsebool checkA = m_checkBtns[0]->checkState();bool checkB = m_checkBtns[1]->checkState();bool checkC = m_checkBtns[2]->checkState();bool checkD = m_checkBtns[3]->checkState();//因为多选要所有答案都对才记分,如果状态不一致那么跳过本次循环if( hasA != checkA) continue;if( hasB != checkB) continue;if( hasC != checkC) continue;if( hasD != checkD) continue;scores += 10;}//判断题计分if(i == 9){//选中项文本和答案文本进行对比if(m_btnGroups[8]->checkedButton()->text() == m_answerList.at(i))scores += 10;}}//如果分数太低,用户想再考一次的话。QString str = "您的分数是:" + QString::number(scores) + "分,是否重新考试?";int res = QMessageBox::information(this,"提示",str,QMessageBox::Yes | QMessageBox::No);if(res == QMessageBox::Yes)return;elseclose();
}

知识点归类

信号与槽完成提交功能

private slots://槽函数——>实现具体的操作:参数4void getScore();    //获取考试成绩connect(submitBtn,SIGNAL(clicked(bool)),this,SLOT(getScore()));

判断“单/多选按——判断按钮”是否被选上了

//单选
m_btnGroups[i]->checkedButton();//成功返回 true,失败返回 false//多选
m_checkBtns[i]->isChecked();//成功返回 true,失败返回 false//判断
m_radioA->isChecked();//成功返回 true,失败返回 false

选中按钮是否包含答案

//contains:是否包含指定的字符串 承购返回:true;失败返回:false
answer.contains("A")

下一篇预告

目前我们分别实现了——登录和获取分数的功能,但是两者没有任何联系,那么我们如何实现两个页面之间的交互呢?

驾校科目一考试系统——窗口交互。

09驾校科目一考试系统——提交分数相关推荐

  1. 10驾校科目一考试系统——窗口交互

    文章目录 回顾 完整代码 Examsys.pro examdialog.h examdialog.cpp logindialog.h logindialog.cpp main.cpp 运行效果 登录页 ...

  2. 06——驾校科目一考试系统——考试时间

    文章目录 考试界面需求分析 具体实现 构建窗体 编写代码 快速在源文件中添加定义小技巧 代码实现 examdialog.h examdialog.cpp 省略登录界面 main.cpp 测试结果 优化 ...

  3. 05——驾校科目一考试系统——验证账号密码

    文章目录 账号密码信息 开始 完整代码 运行 正确输入 错误输入 将密码框进行隐藏 运行结果 下一篇 账号密码信息 开始 回到登录的槽函数. 完整代码 #include "logindial ...

  4. 07——驾校科目一考试系统——布局题库

    文章目录 总代码 examdialog.h examdialog.cpp 运行效果 重要知识点总结(从代码中提炼出来的) 初始化布局 打开文件并设置字符集 将文本框就设置为只读属性 对于文本内数据的操 ...

  5. 03——驾校科目一考试系统——登录界面

    文章目录 需求分析 添加标签 添加输入框 添加按钮 运行项目--初始版本 问题:设计界面和生成大小不同的. 解决方案 运行,成功解决 添加功能--补充背景图 做好准备,添加标签 添加资源 运行项目-- ...

  6. 11驾校科目一考试系统——发布项目

    文章目录 发布项目 修改工作目录 使用windeployqt发布 运行结果 如果还是遇到问题 驾校科目一考试系统完结!! 发布项目   当我们编写完项目之后就需要发布项目 .就需要发布项目了.一般发布 ...

  7. 01——驾校科目一考试系统——需求分析

    目录 需求分析 系统登录 登录界面 需求分析 项目实现 项目精讲 科目考试 需求分析 项目精讲 项目实现 账号管理 需求分析 项目精讲 项目实现 考试题库 需求分析 项目精讲 项目实现 项目拓展 需求 ...

  8. 08——驾校科目一考试——布局按钮

    文章目录 完整版 examdialog.h examdialog.cpp 运行结果 细节剖析 相比于上一版本的新增方法及实现 examdialog.h examdialog.cpp 知识点归类 构造单 ...

  9. 基于Vue的驾校理论课模拟考试系统

    基于Vue的驾校理论课模拟考试系统 系统角色: 系统管理员.普通用户.学员等. 主要功能包括: 定时处理服务器图片到本地.定时获取第三方平台题库.小车.客车.货车试题练习(练习方式包括:顺序练习.习题 ...

最新文章

  1. 出行公司集体亮剑 自动驾驶花落谁家?
  2. java连续输入_java – 要求用户进行多次输入
  3. SQL查询数据库完整表结构(mysql)
  4. python+selenium配置Edge浏览器
  5. P3317-[SDOI2014]重建【矩阵树定理,数学期望】
  6. matlabrobert锐化_基于Matlab的图像锐化的研究
  7. 雷军:疫情影响了小米的生产 正加快小米10系列供货
  8. 测试面经|从测试螺丝钉到大厂测试开发,三点成长心得和面试经验
  9. 2020,2022年全年详细工作日、周末、节假日数据表sql
  10. wps页眉怎么设置不同页码_Word:单双页页眉页码不同怎么设置?不同章节重新编码怎么设置?...
  11. 2D游戏知识点三、Unity生成Android手机apk程序
  12. IDEA 一直Updating indexes问题解决
  13. CSS学习笔记 | CSS复合选择器
  14. 三、自定义Abp Vnext框架代码生成模板
  15. 计算机日常英语句子,计算机英语句子
  16. 如何写出好的SEO标题,网页标题SEO优化的方法
  17. 以企查查为例详解如何用爬虫采集企业信息及电话邮箱数据
  18. “咱们吃鸡吧”的背后
  19. Go语言基础(一篇上手go语言基本语法)
  20. 12月DB-Engines数据库排名,你猜谁会是第一?

热门文章

  1. 【附源码】计算机毕业设计Python安卓基于安卓的豆果美食APPou9ez(源码+程序+LW+调试部署)
  2. 使用Eclipse创建Java应用程序,实现从控制台输出多行信息:姓名、年龄、爱好
  3. 美国全国就业普遍低迷“技术”就业却加速增长;爱立信发布2030年10大消费者趋势 | 美通社头条...
  4. 通过百度语音api实现语音控制五子棋——基于flask
  5. [LUOGU] P3354 [IOI2005]Riv 河流
  6. 浏览器相关及知识积累
  7. 被告没车没房没存款,起诉还有用吗
  8. 中级人力资源管理师(中级经济师)备考攻略
  9. android系统电视升级包下载地址,海美迪HD600A四代官方固件ROM升级包下载_升级教程...
  10. 设计模式01-设计模式中的七大原则