项目源码和资源:科目一考试系统: qt实现科目一考试系统
一.项目概述
该项目是一个基于Qt框架开发的在线考试系统,主要实现了考试题目的随机抽取、考试时间限制、成绩统计等功能。用户可以通过界面操作进行考试,并查看自己的考试成绩。
二.技术栈
Qt框架、C++语言、GUI设计、数据结构、算法等。
三.界面展示
1.登录界面
2.答题界面
3.提交界面
四.代码展示
1.核心要点
整体项目共分为两个部分,登录界面和答题界面,登录界面使用的qt设计器进行手动设计,登录界面核心的点在于使用正则表达式对已有账号进行分析,答题界面核心则是对文件中的试题进行处理。
2.登录界面代码
#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_pushButtonOk_clicked();void on_pushButtonCancel_clicked();private:Ui::LoginDialog *ui;private:void InitUI();
};
#endif // LOGINDIALOG_H
#include "logindialog.h"
#include "ui_logindialog.h"
#include<QIcon>
#include<QMessageBox>
#include<QFile>
#include<QTextStream>LoginDialog::LoginDialog(QWidget *parent): QDialog(parent), ui(new Ui::LoginDialog)
{ui->setupUi(this);InitUI();
}LoginDialog::~LoginDialog()
{delete ui;
}void LoginDialog::InitUI()
{//设置窗口大小int wide=ui->labelimage->width();int height=ui->labelimage->height();this->setGeometry(600,300,wide,height);this->setWindowTitle("科目一考试系统");this->setWindowFlags(Qt::Dialog|Qt::WindowTitleHint);}void LoginDialog::on_pushButtonOk_clicked()
{QRegExp rx("^[a-zA-Z][\\w]{5,17}@([A-Za-z0-9\\-]+\\.)+[A-Za-z]{2,6}$");bool res = rx.exactMatch(ui->lineEditaccount->text());if(!res){//匹配不成功QMessageBox::information(this,"提示","非法的邮箱地址,请你重新输入!");ui->lineEditaccount->clear();ui->lineEditpassword->clear();ui->lineEditaccount->setFocus();//设置光标return;}else{//匹配成功了QString filename; //账号密码数据文件QString strAccInput;//用户输入的账号QString strCode; //用户输入的密码QString strLine; //每次读取的一行数据QStringList strList;//保存分割读取的一行数据filename = "account.txt";//发布时要进行修改strAccInput = ui->lineEditaccount->text();//账号strCode = ui->lineEditpassword->text();//密码QFile file(filename);QTextStream stream(&file);if( file.open(QIODevice::ReadOnly | QIODevice::Text) ){while(!stream.atEnd()){strLine = stream.readLine();strList = strLine.split(",");if(strAccInput == strList.at(0))//账号匹配成功{if(strCode == strList.at(1)){//密码匹配成功QMessageBox::information(this,"提示","欢迎进入科目一考试系统!");file.close();done(Accepted);return;}else{QMessageBox::information(this,"提示","您输入的密码有误,请重新输入!");ui->lineEditpassword->clear();ui->lineEditpassword->setFocus();file.close();return;}}QMessageBox::information(this,"提示","您输入的账号有误,请重新输入!");ui->lineEditaccount->clear();ui->lineEditpassword->clear();ui->lineEditaccount->setFocus();file.close();return;}}else{QMessageBox::information(this,"提示","读取账号数据文件失败!");return;}}}void LoginDialog::on_pushButtonCancel_clicked()
{//关闭窗口this->close();
}
3.答题界面代码
#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
#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,"提示","初始化题库数据文件失败!");QTimer::singleShot(0,qApp,SLOT(quit()));}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;}//过滤答案行if( (nLines >= 6 && nLines <= 6 * 9 && (nLines % 6 == 0) )|| (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;}
}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) + "题");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);break;}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{//单项选择题m_radioBtns[4 * i + j] = new QRadioButton(this);m_radioBtns[4 * i + j]->setText(strList.at(j));m_layout->addWidget(m_radioBtns[4 * i + j],2+j,i);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++){if( m_btnGroups[i]->checkedButton() )radioSelects++;}if(radioSelects != 8)return true;int checkSelects = 0;for(int i = 0; i < 4; i++){if(m_checkBtns[i]->isChecked())checkSelects++;}if(checkSelects == 0 || checkSelects == 1)return true;if(!m_radioA->isChecked() && !m_radioB->isChecked())return true;return false;
}void ExamDialog::freshTime()
{m_timeGo++;QString min = QString::number(m_timeGo / 60);QString sec = QString::number(m_timeGo % 60);setWindowTitle("考试已用时:" + min + "分" + sec + "秒");
}void ExamDialog::getScore()
{if(hasNoSelect()){QMessageBox::information(this,"提示","您有未完成的题目,请完成考试!","是");return;}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;if( answer.contains("A") ) hasA = true;if( answer.contains("B") ) hasB = true;if( answer.contains("C") ) hasC = true;if( answer.contains("D") ) hasD = true;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) 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();
}