Qt 科目一考试系统(有源码)

项目源码和资源:科目一考试系统: qt实现科目一考试系统

一.项目概述

该项目是一个基于Qt框架开发的在线考试系统,主要实现了考试题目的随机抽取、考试时间限制、成绩统计等功能。用户可以通过界面操作进行考试,并查看自己的考试成绩。

二.技术栈

Qt框架、C++语言、GUI设计、数据结构、算法等。

三.界面展示

1.登录界面

2.答题界面

3.提交界面

四.代码展示

1.核心要点

整体项目共分为两个部分,登录界面和答题界面,登录界面使用的qt设计器进行手动设计,登录界面核心的点在于使用正则表达式对已有账号进行分析,答题界面核心则是对文件中的试题进行处理。

2.登录界面代码

cpp 复制代码
#ifndef LOGINDIALOG_H
#define LOGINDIALOG_H

#include <QDialog>

QT_BEGIN_NAMESPACE
namespace Ui { class LoginDialog; }
QT_END_NAMESPACE

class LoginDialog : public QDialog
{
    Q_OBJECT

public:
    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
cpp 复制代码
#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.答题界面代码

cpp 复制代码
#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
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,"提示","初始化题库数据文件失败!");
        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;
    else
        close();
}


   
相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript