【qt】考试系统项目

话不多说,先一睹芳颜
在这里插入图片描述

咱们的账号,题库和答案都是通过文件获取的.
话不多说,直接开干

目录

  • 一.登录窗口
    • 1.界面设计
    • 2.邮箱验证
    • 3.登录验证
  • 二.题库窗口
    • 1.考试计时
    • 2.布局管理器
    • 3.题库显示
    • 4.按钮布局
    • 5.计算分数
  • 三.窗口交互
  • 四.完整代码
  • 五.结语

一.登录窗口

1.界面设计

在这里插入图片描述
在这里插入图片描述
这里添加背景图片.
在这里插入图片描述
密码输入模式和提示语句.
在这里插入图片描述

注意:背景图标放在的标签必须要第一个,不然会盖住其他组件.

2.邮箱验证

在这里插入图片描述

用正则表达式来进行判断.

3.登录验证

在这里插入图片描述
第一行读取的话,要跳过,我们不用.
在这里插入图片描述
中间有多个空格,所以我们可以使用正则表达式来进行匹配来获取子串.

在这里插入图片描述
如果循环完都没有找到就说明我们输入的账号有问题,所以这个是循环读取外面加的.

二.题库窗口

1.考试计时

需要用到计时器
在这里插入图片描述
每隔一秒,我们就发出timeout()这个信号.
在这里插入图片描述
然后计算分秒来设置在窗口的标题上.

在这里插入图片描述
对窗口进行一点的渲染.

2.布局管理器

这是一个神器,当我们用代码来写组件的时候,有了它,你可以高枕无忧的布局.
在这里插入图片描述
下面我们布局组件的时候可以来看布局管理器怎么使用.

3.题库显示

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
定义了这个来保存我们的答案,方便我们后面计算分数.

在这里插入图片描述
添加到组件上,并使用布局管理器.
第一个参数是要添加布局的组件
第二三个参数是这个组件的位置,可以把布局管理器理解成一个表格,从0行0列开始
第四五哥参数是这个组件所占的行数和列数.

4.按钮布局

在这里插入图片描述
用的组件数组来初始化.

在这里插入图片描述
在这里插入图片描述
初始化单选题的时候,我们要进行分组,这样才可以每个题选一项.
同时添加到布局管理器中.

在这里插入图片描述
初始化按钮并关联槽函数,来计算分数.

5.计算分数

在这里插入图片描述
在计算分数前,我们先来判断是否所有的题都已答完,若没有就继续.
在这里插入图片描述
单选题只需要判断每个单选组里面有没有选择的即可.
多选题记一下数,看是不是大于等于2即可

接下来就是正式的算分了.
多选题的算分比较复杂
在这里插入图片描述
先获取答案中有那些选项,我们用bool类型来设置状态.
然后与多选框的每个选项状态一一对比.
完全一样才得分.

在这里插入图片描述
单选题和判断题都从按钮组中获取到文本来与我们先前获取到的答案进行对比.
在这里插入图片描述
显示分数,并给用户选择是否重新答题.

三.窗口交互

现在,我们的两个窗口都写好了,怎么衔接起来呢?
在这里插入图片描述
在这里插入图片描述
这个可以关闭当前的窗口,并返回一种用户点击的信息.

在这里插入图片描述
在main中用模态的方式,来进行接受信息.
并构造我们的考试窗口.
在考试窗口的构造函数中进行显示,以防未初始化窗口就进行显示.
在这里插入图片描述

四.完整代码

examdialog.h

#ifndef EXAMDIALOG_H
#define EXAMDIALOG_H
#include <QDialog>
#include <QTimer>
#include <QGridLayout>
#include <QTextEdit>
#include <QRadioButton>
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QButtonGroup>class ExamDialog : public QDialog
{Q_OBJECT
public:ExamDialog(QWidget *parent=0);void initTimer();void initLayout();bool initTextEdit();void initButton();bool hasSelected();void getScores();private:QTimer*m_timer;int m_sec=0;QGridLayout*m_layout;QTextEdit*m_textEdit;QLabel*m_label[10];QRadioButton*m_radioBtn[32];QRadioButton*m_radioA;QRadioButton*m_radioB;QCheckBox*m_CheckBoxBtn[4];QStringList answers;QButtonGroup*BtnGroup[9];private slots:void onTimeout();void onBtn();
};#endif // EXAMDIALOG_H

examdialog.cpp

#include "examdialog.h"
#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QMessageBox>ExamDialog::ExamDialog(QWidget *parent):QDialog(parent)
{resize(800,900);this->setWindowTitle("已考试: 0分0秒");QFont font;font.setPointSize(20);this->setFont(font);setPalette(QPalette(QColor(213,81,213)));setWindowFlags(Qt::Dialog|Qt::WindowCloseButtonHint);initTimer();initLayout();if(!initTextEdit()){QTimer::singleShot(0,qApp,SLOT(quit()));}initButton();show();//都初始化成功,我才显示.
}void ExamDialog::initTimer()
{m_timer=new QTimer(this);m_timer->setInterval(1000);m_timer->start();connect(m_timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
}void ExamDialog::initLayout()
{m_layout=new QGridLayout(this);m_layout->setSpacing(10);m_layout->setMargin(10);
}bool ExamDialog::initTextEdit()
{m_textEdit=new QTextEdit(this);m_textEdit->setReadOnly(true);QString fileName="../tk.txt";QFile file(fileName);QTextStream stream(&file);stream.setCodec("UTF-8");if(!file.open(QIODevice::ReadOnly|QIODevice::Text))return false;QString line;QStringList list;QString passage;int nline=0;while (!stream.atEnd()){if(nline==0){stream.readLine();nline++;continue;}if((nline>=6&&nline<=6*9&&(nline%6==0))||(nline==6*9+4)){line=stream.readLine();list=line.split(" ");answers.append(list.at(1));//服了passage+="\n";nline++;continue;}line=stream.readLine();passage+=line;passage+="\n";nline++;}m_textEdit->setText(passage);m_layout->addWidget(m_textEdit,0,0,1,10);file.close();return true;
}void ExamDialog::initButton()
{QStringList chooseList={"A","B","C","D"};for(int i=0;i<10;i++){m_label[i]=new QLabel(this);m_label[i]->setText("第"+QString::number(i+1)+"题");m_layout->addWidget(m_label[i],1,i);if(i==8){for(int j=0;j<4;j++){m_CheckBoxBtn[j]=new QCheckBox(this);m_CheckBoxBtn[j]->setText(chooseList[j]);m_layout->addWidget(m_CheckBoxBtn[j],j+2,i);}continue;}if(i==9){m_radioA=new QRadioButton(this);m_radioA->setText("对");m_radioB=new QRadioButton(this);m_radioB->setText("错");BtnGroup[8]=new QButtonGroup(this);BtnGroup[8]->addButton(m_radioA);BtnGroup[8]->addButton(m_radioB);m_layout->addWidget(m_radioA,2,i);m_layout->addWidget(m_radioB,3,i);continue;}BtnGroup[i]=new QButtonGroup(this);for(int j=0;j<4;j++){m_radioBtn[i*4+j]=new QRadioButton(this);m_radioBtn[i*4+j]->setText(chooseList[j]);BtnGroup[i]->addButton(m_radioBtn[i*4+j]);m_layout->addWidget(m_radioBtn[i*4+j],2+j,i);}}QPushButton *Btn=new QPushButton(this);Btn->setText("提交");m_layout->addWidget(Btn,6,9);connect(Btn,SIGNAL(clicked()),this,SLOT(onBtn()));
}bool ExamDialog::hasSelected()
{int checkCount=0;for(int j=0;j<4;j++){if(m_CheckBoxBtn[j]->isChecked()){checkCount++;}}if(checkCount==0||checkCount==1){return false;}for(int i=0;i<9;i++){if(!BtnGroup[i]->checkedButton()){return false;}}return true;}void ExamDialog::getScores()
{int score=0;for(int i=0;i<10;i++){if(i==8){QString answer=answers.at(i);bool hasA=false;bool hasB=false;bool hasC=false;bool hasD=false;if(answer.contains("A")) hasA=true;if(answer.contains("B")) hasB=true;if(answer.contains("C")) hasC=true;if(answer.contains("D")) hasD=true;if(m_CheckBoxBtn[0]->isChecked()==hasA&&m_CheckBoxBtn[1]->isChecked()==hasB&&m_CheckBoxBtn[2]->isChecked()==hasC&&m_CheckBoxBtn[3]->isChecked()==hasD){score+=10;}continue;}if(i==9){QString answer=answers.at(i);if(BtnGroup[8]->checkedButton()->text()==answer){score+=10;}continue;}if(BtnGroup[i]->checkedButton()->text()==answers[i]){score+=10;}}int res=QMessageBox::information(this,"提示","您的考试分数为:"+QString::number(score)+"分,是否需要重新考试?",QMessageBox::Yes|QMessageBox::No);if(res==QMessageBox::Yes){return;}else{close();}
}void ExamDialog::onTimeout()
{m_sec++;int minute=m_sec/60;int sec=m_sec%60;this->setWindowTitle("已考试: "+QString::number(minute)+"分"+QString::number(sec)+"秒");
}void ExamDialog::onBtn()
{if(!hasSelected()){QMessageBox::information(this,"提示","题没作答完,请继续作答!");}else{getScores();}
}

logindialog.h

#ifndef LOGINDIALOG_H
#define LOGINDIALOG_H#include <QDialog>QT_BEGIN_NAMESPACE
namespace Ui { class loginDialog; }
QT_END_NAMESPACEclass loginDialog : public QDialog
{Q_OBJECTpublic:loginDialog(QWidget *parent = nullptr);~loginDialog();private slots:void on_pushButtonLogin_clicked();void on_pushButtonCancel_clicked();private:Ui::loginDialog *ui;void loginFromFile();
};
#endif // LOGINDIALOG_H

logindialog.cpp

#include "logindialog.h"
#include "ui_logindialog.h"
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QDebug>loginDialog::loginDialog(QWidget *parent): QDialog(parent), ui(new Ui::loginDialog)
{ui->setupUi(this);ui->label->setScaledContents(true);resize(ui->label->width(),ui->label->height());setFixedSize(ui->label->width(),ui->label->height());setWindowFlags(Qt::Dialog|Qt::WindowCloseButtonHint);setWindowTitle("考试系统");
}loginDialog::~loginDialog()
{delete ui;
}void loginDialog::on_pushButtonLogin_clicked()
{QRegExp reg("^[A-Za-z0-9]+(_[A-Za-z0-9]+)*@[A-Za-z0-9]+(_[A-Za-z0-9]+)*\.[A-Za-z]{2,6}$");bool res=reg.exactMatch(ui->lineEditAccount->text());if(res){loginFromFile();}else{QMessageBox::information(this,"提示","邮箱格式有误,请重新输入!");ui->lineEditPWD->clear();ui->lineEditAccount->clear();ui->lineEditAccount->setFocus();return;}
}void loginDialog::loginFromFile()
{QString line;QString account;QString pwd;QStringList list;int nline=0;account=ui->lineEditAccount->text();pwd=ui->lineEditPWD->text();QString fileName("../account.txt");QFile file(fileName);QTextStream stream(&file);if(!file.open(QIODevice::ReadOnly|QIODevice::Text))return;while(!stream.atEnd()){if(nline==0){stream.readLine();nline++;continue;}line=stream.readLine();QRegExp reg("\\s+");list=line.trimmed().split(reg);nline++;if(account==list.at(0)){if(pwd==list.at(1)){QMessageBox::information(this,"提示","登录成功,欢迎进入考试系统!");file.close();done(Accepted);return;}else{QMessageBox::information(this,"提示","密码输入有误,请重新输入!");ui->lineEditPWD->clear();ui->lineEditPWD->setFocus();file.close();return;}}}QMessageBox::information(this,"提示","账户输入有误,请重新输入!");ui->lineEditAccount->clear();ui->lineEditPWD->clear();ui->lineEditAccount->setFocus();file.close();return;
}void loginDialog::on_pushButtonCancel_clicked()
{done(Rejected);
}

main.cpp

#include "logindialog.h"#include <QApplication>
#include "examdialog.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);loginDialog w;int res=w.exec();if(res==QDialog::Accepted){ExamDialog *examDialog=new ExamDialog;        }else{return 0;}return a.exec();
}

五.结语

当然这个读取文件没有自适应,需要根据你的文件内容进行调整.
完结撒花.

好想到筑基期呀.君子生非异也,善假于物也.

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

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

相关文章

【笔记】先求修改没保存的文本文件-在虚拟机中输入 yum makecache报错

所有者: root 日期: Sat Jul 13 03:10:34 2024 文件名: /etc/yum.repos.d/CentOS-Base.repo 修改过: 是 用户名: root 主机名: linuxlocalhost 进程 ID: 78107 正在打开文件 "CentOS-Base.repo" 日期: Sat Jul 13 03:18:24 2024 比交换文件新&#xff01; (1) Anothe…

从信息化、数字化、智能化到企业大模型应用

新时代背景下&#xff0c;数字经济发展速度之快、辐射范围之广、影响程度之深前所未有&#xff0c;5G、大数据、云计算、人工智能、区块链等技术加速创新&#xff0c;全域融入经济社会、民生服务全过程&#xff0c;成为资源要素重组、经济结构重塑、竞争格局重构的关键力量。千…

jar服务注册为windows的服务

依赖工具&#xff1a;nssm.exe 使用NSSM (Non-Sucking Service Manager) NSSM是一个免费的开源工具&#xff0c;用于将任何应用程序注册为Windows服务。以下是如何使用NSSM将Java应用注册为服务的步骤&#xff1a; 步骤 1: 安装 NSSM 首先&#xff0c;你需要从NSSM的官方网站…

Visual Studio 安装程序无法执行修复或更新

一.问题场景 出现问题的场景&#xff1a;当你的VS已经安装但是无法在工具中下载新组件或者卸载了当时一直无法安装。 二.问题原因 如果计算机上的 Visual Studio 实例已损坏&#xff0c;则可能会出现此问题。 三.解决方法 如果之前尝试修复或更新 Visual Studio 失败&…

【Python】 使用 gne 库提取新闻标题的简易指南

我白天是个 搞笑废物 表演不在乎 夜晚变成 忧伤怪物 撕扯着孤独 我曾经是个 感性动物 小心地感触 现在变成 无关人物 &#x1f3b5; 张碧晨/王赫野《何物》 数据科学和网络爬虫领域&#xff0c;提取网页内容是一项常见任务。然而&#xff0c;不同的网站结…

浅谈RLHF---人类反馈强化学习

浅谈RLHF&#xff08;人类反馈强化学习&#xff09; RLHF&#xff08;Reinforcement Learning fromHuman Feedback&#xff09;人类反馈强化学习 RLHF是[Reinforcement Learning from Human Feedback的缩写&#xff0c;即从人类反馈中进行强化学习。这是一种结合了机器学习中…

Gridea + SFTP +Docker + Nginx 配置博客-CSDN

服务器选择 阿里云 ESC 服务器 比较便宜 99 一年开启密码登录配置你的远程服务域名选择自己的域名&#xff0c;当然我可以解析二级域名给大家不要搞我的服务器Remote Path 远程服务配置 配置自己的一个文件夹我是使用的 /gridea/blog &#xff08;绝对路径&#xff09;阿里云安…

探索AI艺术:简单方法训练你的AI画家(思路)

如何训练一个简单的AI画家模型 1. 确定问题和目标 在开始之前&#xff0c;明确你想要的输出类型和风格。例如&#xff0c;你是否想要生成逼真的风景画&#xff0c;还是抽象艺术作品&#xff1f;这将决定你选择的模型和数据集。 2. 准备数据集 收集和准备用于训练的艺术作品…

51单片机6(P0P1P2P3结构框架图)

一、GPIO结构框架图与工作原理 1、接下来我们介绍一下这个GPIO结构框图和工作原理&#xff0c;我们使用51单片机的GPIO分为了P0&#xff0c;P1&#xff0c;P2&#xff0c;P3这四组端口&#xff0c;下面我们就分别来介绍这四组端口它的一个内部结构&#xff0c;只有了解了内部的…

【React】监听浏览器返回事件

文章目录 popstate事件&#xff1a;点击浏览器前进&#xff0c;后退会触发popstate事件即&#xff0c;在同一文档的两个历史记录条目之间导航会触发该事件 useEffect(() > {const handlePageBack () > {// 此处写你想要触发的事件console.log(浏览器返回按钮被点击了&a…

[PM]原型与交互设计

原型分类 1.草图原型 手绘图稿, 规划的早期,整理思路会使用 2.低保真原型 简单交互, 无需配色, 黑白灰为主, 产品规划和评审阶段使用 标准化的低保真原型是高保真原型的基础 3.高保真原型 复杂交互, 一般用于公开演示, 产品先产出低保真原型, 设计师根据原型产出设计稿 低保…

Vue3学习体验(一)

搭建工程 使用vue-cli脚手架创建vue3工程 vue create vue3-app-vue-cliVue-cli官网&#xff1a;https://cli.vuejs.org/zh/guide/installation.html 使用vite搭建vue3工程 npm init表示临时的下载vite应用来创建vue3工程&#xff0c;工程名称为vue3-app-vite npm init vit…

mount挂载

1&#xff09;Vmvare挂载光驱设备 安装光驱设备后&#xff0c;可以看到设备文件。 ls /dev/sr0 ll /dev/cdrom虽然设备是以文件的形式出现的&#xff0c;但和一般的文件不一样。 2&#xff09;mount挂载 目录是目录&#xff0c;设备是设备&#xff0c;mount挂载可以让目录成…

数据结构——查找(线性表的查找与树表的查找)

目录 1.查找 1.查找的基本概念 1.在哪里找&#xff1f; 2.什么查找&#xff1f; 3.查找成功与否&#xff1f; 4.查找的目的是什么&#xff1f; 5.查找表怎么分类&#xff1f; 6.如何评价查找算法&#xff1f; 7.查找的过程中我们要研究什么&#xff1f; 2.线性表…

Spring webflux基础核心技术

一、 用操作符转换响应式流 1 、 映射响应式流元素 转换序列的最自然方式是将每个元素映射到一个新值。 Flux 和 Mono 给出了 map 操作符&#xff0c;具有 map(Function<T&#xff0c;R>) 签名的方法可用于逐个处理元素。 当操作符将元素的类型从 T 转变为 R 时&#xf…

OpenCV和CUDA匹配,使用源码构建OpenCV

当你使用pip安装opencv-contrib-python时&#xff0c;实际上你是在安装一个预编译的二进制包&#xff0c;这个包并不包含源代码。预编译的包是为特定的Python版本和操作系统架构准备的&#xff0c;所以当你安装时&#xff0c;你不需要源代码&#xff0c;也不需要使用CMake或进行…

qt 获取父控件

在 Qt 中&#xff0c;你可以通过调用 QWidget 的 parentWidget() 方法来获取一个控件的父控件。这个方法会返回一个指向父控件的指针&#xff0c;如果该控件没有父控件&#xff0c;则返回 nullptr。 以下是一个简单的示例&#xff0c;展示了如何获取一个按钮的父控件&#xff…

基于conda包的环境创建、激活、管理与删除

Anaconda是一个免费、易于安装的包管理器、环境管理器和 Python 发行版&#xff0c;支持平台包括Windows、macOS 和 Linux。下载安装地址&#xff1a;Download Anaconda Distribution | Anaconda 很多不同的项目可能需要使用不同的环境。例如某个项目需要使用pytorch1.6&#x…

SAP 消息输出 - Adobe Form

目录 1 安装链接 2 前台配置 - Fiori app 2.1 维护表单模板 (maintain form templates) 2.2 管理微标 (manage logos) 2.3 管理文本 (manage texts) 3 后台配置 3.1 定义表单输出规则 3.2 分配表单模板 SAP 消息输出&#xff0c;不仅是企业内部用来记录关键业务操作也是…

WPF中Frame

在Windows Presentation Foundation (WPF) 中&#xff0c;Frame 控件是一个非常重要的元素&#xff0c;主要用于实现页面导航和内容的动态加载。Frame 类似于网页开发中的iframe&#xff0c;但它是WPF应用程序中的一个容器&#xff0c;能够显示不同的页面或控件内容。 以下是F…