目录

1.设置登录界面

2.登录功能实现

2.1验证邮箱地址

2.2账号密码登录

2.3密码隐藏

3.考试界面开发

3.1考试用时

3.2题目布局

3.3按钮布局

3.4提交分数

3.5窗口交互

4.发布项目

4.1更改编译路径

4.2设置图标

4.3通过dos进行项目打包


1.设置登录界面

LoginDialog::LoginDialog(QWidget *parent) :QDialog(parent),ui(new Ui::LoginDialog)
{ui->setupUi(this);ui->imgLabel->setScaledContents(true);//设置填充this->resize(ui->imgLabel->width(),ui->imgLabel->height());//设置窗口大小//设置窗口标题this->setWindowTitle(("驾校科目一考试登录"));//设置窗口风格this->setWindowFlags(Qt::Dialog |Qt::WindowCloseButtonHint);
}

2.登录功能实现

2.1验证邮箱地址

首先判断输入的账号是否符合邮箱格式 ,如果符合则进行登录验证,否则提示格式错误

void LoginDialog::on_loginButton_clicked()
{//首先通过正则表达式判断账号是否是一个合法的邮箱格式//^:表示规则字符串开始、$:表示规则字符串的结束//+:表示匹配次数≥1次、*:表示匹配任意次数(可为0次) {n,m}表示匹配次数最少n次 最多m次QRegExp rx("^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$");//初始化时指定规则字符串bool res = rx.exactMatch(ui->accountEdit->text());//对用户输入的账号进行匹配if(res){//匹配成功QMessageBox::information(this,"提示","欢迎登录科目一考试科目系统");}else{//匹配不成功QMessageBox::information(this,"提示","非法邮箱地址!请您重新输入");ui->accountEdit->clear();//清空账号输入框ui->codeEdit->clear();//清空密码输入框ui->accountEdit->setFocus();//账号输入框聚焦return ; }}

2.2账号密码登录

当账号格式合法后,读取保存账号和密码的文档进行匹配

if(res){//匹配成功
//QMessageBox::information(this,"提示","欢迎登录科目一考试科目系统");
QString filename;//文件路径
QString AccInput;//用户输入账号
QString strCode;//用户输入密码
QString strLine;//每次读取一行数据
QStringList strList;//分割读取一行数据filename="../account.txt";//设置文件路径
AccInput=ui->accountEdit->text();//获取账号
strCode=ui->codeEdit->text();//获取密码QFile file(filename);//初始化
QTextStream stream(&file);//文本类型文件流
//指定只读方式打开,指定文件类型式文本类型
if(file.open(QIODevice::ReadOnly|QIODevice::Text)){//打开成功while(!stream.atEnd()){strLine=stream.readLine();//每次读取一行strList = strLine.split(",");//将读取到的行按","分割if(AccInput==strList.at(0)){if(strCode==strList.at(1)){//账号和密码匹配成功QMessageBox::information(this,"提示","欢迎进入科目一考试系统");file.close();return ;}else{//账号匹配成功&密码不成功QMessageBox::information(this,"提示","密码错误!请重新输入!");ui->codeEdit->clear();ui->codeEdit->setFocus();file.close();return ;}}}QMessageBox::information(this,"提示","输入账号有误!请重新输入!");ui->accountEdit->clear();//清空账号输入框ui->codeEdit->clear();//清空密码输入框ui->accountEdit->setFocus();//账号输入框聚焦file.close();return;
}

2.3密码隐藏

将密码控件的echoMode属性值改为Password即可

3.考试界面开发

3.1考试用时

首先添加一个考试对话框类;在考试对话框类中添加QTimer和int属性用于表示计时器和已用时;设定计时器的时间间隔为1s,通过connect函数将计时器与已用时显示信号槽连接起来

examDialog.h

#ifndef EXAMDIALOG_H
#define EXAMDIALOG_H
#include<QDialog>
#include<QTimer>
class ExamDialog : public QDialog
{Q_OBJECT//使用信号槽
public:ExamDialog(QWidget* parent=0);void initTimer();
private:QTimer*m_timer;//计时器int m_timeGo;//考试已用时
private slots:  //私有槽方法void freshTime();
};#endif // EXAMDIALOG_H

examDialog.cpp

#include "examdialog.h"ExamDialog::ExamDialog(QWidget* parent):QDialog(parent)
{setWindowTitle("考试已用时:0分0秒");initTimer();
}void ExamDialog::initTimer()
{m_timeGo=0;m_timer=new QTimer(this);m_timer->setInterval(1000);//设置计时器时间间隔1sm_timer->start();//启动计时器//通过connect方法,连接信号槽。m_timer每发送timeout()信号时,由this执行槽方法freshTime()connect(m_timer,SIGNAL(timeout()),this,SLOT(freshTime()));}void ExamDialog::freshTime()
{//刷新考试用时m_timeGo++;QString min=QString::number(m_timeGo/60);//计算分钟,将整数转QStringQString sec=QString::number(m_timeGo%60);setWindowTitle("考试已用时:"+min+"分"+sec+"秒");
}

3.2题目布局

添加属性以及初始化方法

public:void initLayout();  //初始化布局管理器bool initTextEdit();//初始化文本编辑器void initButton();  //初始化按钮及标签
private:QTextEdit*m_textEdit;       //考试题库显示QLabel*m_titleLabels[10];   //题目标签QRadioButton *m_radioBtns[32];//单选按钮QCheckBox *m_checkBtn[4];   //多选题按钮QRadioButton *m_radioA;     //判断题A选项QRadioButton *m_radioB;     //判断题B选项QGridLayout*m_layout;       //布局管理器QStringList m_answerList;   //答案

在initLayout函数中,设置当前窗口为为管理器父窗口,规定控件间的距离以及控件和窗体间的距离

void ExamDialog::initLayout()
{//以当前窗口作为父窗口m_layout=new QGridLayout(this);m_layout->setSpacing(10);//设置控件之间的间距m_layout->setMargin(10);//设置窗体与控件键的边距}

在initTextEdit函数中,读取文本中的题目信息并将答案行单独存储,将读取到的题目信息显示在控件中,并将控件交给布局管理器在窗体上布局。

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;}else if((nLines%6==0&&nLines>=6&&nLines<=6*9)||nLines==6*9+4){//过滤答案行strLine = stream.readLine();strList=strLine.split(" ");//通过空格分割出答案行的答案m_answerList.append(strList.at(1));//获得答案strText+="\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;}
}

在初始化函数中对窗体背景和字体进行一些设置

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()){}else{//读取失败QMessageBox::information(this,"提示","初始化题库数据文件失败!");//当前应用程序立刻响应槽方法quitQTimer::singleShot(0,qApp,SLOT(quit()));}
}

3.3按钮布局

布局方法就是先将控件初始化,然后交给布局管理器进行布局。但要注意的是单选按钮的分组:每个单选题的四个按钮为一组,判断题的两个按钮为一组

新添加QbuttonGroup属性

private:QButtonGroup* m_btnGroups[9];//单选按钮分组

在初始换按钮函数中

void ExamDialog::initButton()
{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)+"题");m_layout->addWidget(m_titleLabels[i],1,i);//交给布局管理器,默认是占据一行一列//判断题if(i==9){m_radioA=new QRadioButton(this);m_radioB=new QRadioButton(this);m_radioA->setText("正确");m_radioB->setText("错误");m_layout->addWidget(m_radioA,2,9);m_layout->addWidget(m_radioB,3,9);//判断题按钮分组m_btnGroups[8]=new QButtonGroup(this);m_btnGroups[8]->addButton(m_radioA);m_btnGroups[8]->addButton(m_radioB);}if(i<8){//单选题按钮分组m_btnGroups[i]=new QButtonGroup(this);}//选择题for(int j=0;j<4;++j){if(i==8){//多选题m_checkBtns[j]=new QCheckBox(this);m_checkBtns[j]->setText(strList.at(j));m_layout->addWidget(m_checkBtns[j],2+j,8);}else if(i<8){//单选题m_radioBtns[i*4+j]=new QRadioButton(this);m_radioBtns[i*4+j]->setText(strList.at(j));m_layout->addWidget(m_radioBtns[i*4+j],2+j,i);m_btnGroups[i]->addButton(m_radioBtns[i*4+j]);}}//提交按钮QPushButton*submitBtn=new QPushButton(this);submitBtn->setText("提交");submitBtn->setFixedSize(100,35);m_layout->addWidget(submitBtn,6,9);}
}

3.4提交分数

首先将提交按钮与信号槽连接

connect(submitBtn,SIGNAL(clicked(bool)),this,SLOT(getScore()));

在计算分数前先判断题目是否全部完成,然后根据读取的答案计算分数

bool ExamDialog::hasNoSelect()
{int radioSelects=0;//统计单选题完成数量for(int i=0;i<8;++i){if(m_btnGroups[i]->checkedButton()){radioSelects++;}}//判断单选题是否全部完成if(radioSelects!=8){return true;}//统计多选题选择数量int checkSelect=0;for(int i=0;i<4;++i){if(m_checkBtns[i]->isChecked()){checkSelect++;}}//多选题未选或只选了一个也算未完成if(checkSelect==0||checkSelect==1){return true;}//判断题if(!m_radioA->isChecked()&&!m_radioB->isChecked()){return true;}return false;
}void ExamDialog::getScore()
{if(hasNoSelect()){//有未完成的题目QMessageBox::information(this,"提示","您有未完成的题目!请完成考试","是");return ;}else{//开始统分int scores =0;for(int i=0;i<10;++i){//单选题统分if(i<8){//判断选中的按钮与答案的是否一致if(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;hasA=answer.contains("A");hasB=answer.contains("B");hasC=answer.contains("C");hasD=answer.contains("D");bool 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||hasB!=checkB||hasC!=checkC||hasD!=checkD){//答案有不一致的continue;}else{scores+=10;}}//判断题统分if(i==9){if(m_btnGroups[8]->checkedButton()->text()==m_answerList.at(i)){scores+=10;}}}int res = QMessageBox::information(this,"提示","您所得分数为:"+QString::number(scores)+"分。是否重新考试?",QMessageBox::Yes|QMessageBox::No);if(res==QMessageBox::Yes){//重新考试return;}else{//不想重新考试close();}}
}

3.5窗口交互

实现登录窗口与考试窗口的连接

当用户登录成功后通过done函数发送一个Accepted,当用户点击取消时发送一个Rejected,然后在主函数中进行判断

int main(int argc, char *argv[])
{QApplication a(argc, argv);LoginDialog loginDialog;int res = loginDialog.exec();   //以模态方式运行if(res==QDialog::Accepted){ExamDialog examDialog;return a.exec();}else{return 0;}return a.exec();
}

4.发布项目

4.1更改编译路径

将当前编译路径由debug转为当前文件所在路径

4.2设置图标

在项目文件中通过 RC_ICONS加载图标

RC_ICONS += examsys.ico

图标已经更改过来了

4.3通过dos进行项目打包

将项目由DeBug模式改为Release模式,并编译

建立一个文件夹作为发布文件,将Release下生成的.exe文件和需要的文档拷贝进来

进入要发布文件夹路径,然后输入windeployqt 文件名.exe,点击回车

打包完成

如果提示 windeployqt不是命令的话需要将安装的qt的bin路径添加到环境变量中

项目完成✌✌✌

QT驾校科目考试系统——从实现到发布相关推荐

  1. Qt - 驾校科目-考试系统-窗口交互

    Qt - 驾校科目-考试系统-窗口交互 如果登录成功 编译执行 这样子就能避免一闪而过(方法一) 编译执行也没有问题 内存分配方法(二) #ifndef EXANDIALOG_H #define EX ...

  2. 基于android驾校模拟考试系统app

    驾驶理论考试就是在线考试的一个实际应用,它实现了理论考试的无纸化,以往出题.印试卷.批改试卷等繁琐的工作,现在都可以由计算机来替代.本系统有驾校模拟考试功能,包括用户管理及试题库管理.试卷管理和随机出 ...

  3. 【程序源代码】驾校模拟考试系统

    " 关键字: 驾校模拟考试系统 学习案例 " 正文:驾校模拟考试系统 驾校模拟考试系统 软件架构 springboot+vue        适合对象 学生.前端工程师.后端开发工 ...

  4. 【程序源代码】VUE驾校模拟考试系统

    " 关键字: 驾校模拟考试系统 学习案例 " 正文:驾校模拟考试系统 驾校模拟考试系统 软件架构 vue主要就是使用了vue这个框架,        适合对象 学生.前端工程师.后 ...

  5. 考试系统mysql数据库设计_驾校理论考试系统之数据库设计一

    应用开发工具:Microsoft Visual Studio 2010 旗舰版 - 简体中文 sp1-- Microsoft Visual C# 2010 应用程序:文档处理:Microsoft Of ...

  6. 基于Android的驾照(驾校)考试系统的设计与实现

    系统使用uni-app实现,会简单的HTML和PHP基础知识即可看懂: 代码: public class DBHelper {private ConnDB db = null;// 声明连接对象pri ...

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

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

  8. 基于Android驾校理论模拟考试系统APP

    驾驶理论考试就是在线考试的一个实际应用,它实现了理论考试的无纸化,以往出题.印试卷.批改试卷等繁琐的工作,现在都可以由计算机来替代.本系统有驾校模拟考试功能,包括用户管理及试题库管理.试卷管理和随机出 ...

  9. Android驾校理论模拟考试系统APP毕业设计

    驾驶理论考试就是在线考试的一个实际应用,它实现了理论考试的无纸化,以往出题.印试卷.批改试卷等繁琐的工作,现在都可以由计算机来替代.本系统有驾校模拟考试功能,包括用户管理及试题库管理.试卷管理和随机出 ...

最新文章

  1. UICollectionView入门--使用系统UICollectionViewFlowLayout布局类
  2. 线程池之ScheduledThreadPool学习
  3. Vue中用TypeScript改写JavaScript及装饰器使用
  4. golang 使用 http socks 代理
  5. can与could区别
  6. C# Web实时消息后台服务器推送技术---GoEasy
  7. Java 面试题 —— 老田的蚂蚁金服面试经历
  8. chmod g+s 、chmod o+t 、chmod u+s
  9. asp.net mvc使用的心得和问题的解决方法(陆续更新ing)
  10. python控制浏览器导出数据_Django导出数据为Excel,调用浏览器下载
  11. pyqt label上的图片旋转_python中tkinter入门之config、Scale、Canvas和导入图片
  12. laravel 运用
  13. MySQL系列(三)
  14. Log4net日志记录包
  15. 三星note9刷Android9,三星Note9国行安卓9固件rom刷机包CHC-N9600ZCS1CSD1四件套
  16. 如何用U盘安装Windows操作系统
  17. element-ui下拉框全选
  18. rfid射频前端的主要组成部分有_超高频RFID电子标签的组成
  19. opencv,获取图片
  20. 删除字符串某一指定子字符串

热门文章

  1. java 中的 while和 do...while语句的区别
  2. 6、python-mongodb获取数据存储到sql server
  3. 视频转图片序列 java_怎样才能把一段视频转换成序列图片文件
  4. 网页加载,只显示文字,不显示图片。(原因解决方法)
  5. 树形结构表3种设计优劣分析与分享
  6. 宝峰数科带你读懂数字家庭的真正内涵
  7. python pandas 分割DataFrame中的字符串及元组
  8. 【Python数据清洗】pivot_table 与 pivot 的区别——手把手系列
  9. 第5天-[21天学Python]-Python中自定义函数及调用的方法
  10. OA系统与MES系统的异同点