【qt】考试系统项目

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

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

一.登录窗口

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_NAMESPACE

class loginDialog : public QDialog
{
    Q_OBJECT

public:
    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();
}

五.结语

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

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

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt C 考试系统 是一个开源项目,它是使用Qt C++框架开发的。这个考试系统的目的是为了方便教育机构或培训机构进行在线考试管理和促进学生的学习。 这个考试系统具有以下主要特点: 1. 灵活的题目管理方式:该系统允许管理员轻松地添加、编辑和删除题目。这些题目可以根据不同的学科、难度级别或类型进行分类,方便管理员和教师进行题目的组织和使用。 2. 多种题型支持:考试系统支持多种常见的题型,如选择题、填空题、判断题和主观题等。这样可以满足不同学科和不同难度级别的考试需求,并能全面评估学生的能力。 3. 自动化的评分和反馈:一旦学生完成考试,系统将自动对答案进行评分,并生成详细的成绩报告。学生可以及时查看自己的得分和评语,教师也可以根据这些成绩报告提供针对性的反馈和指导。 4. 安全可靠的考试环境:该系统采用了一系列安全机制,确保考试过程的安全性和公平性。例如,系统能够防止作弊行为,保护学生的答案不被泄露。 5. 友好的用户界面:系统使用了Qt C++框架开发,因此拥有直观友好的用户界面。学生和教师可以轻松地进行操作和使用系统的各项功能。 总而言之,Qt C 考试系统 是一个功能强大且易于使用的开源项目,它可以有效地管理考试过程,提供准确和及时的评分和反馈,为教育机构和学生提供更好的学习和评估体验。 ### 回答2: QT C 考试系统是一个开源的项目,它基于QT框架和C语言开发,用于实现在线考试的功能。该系统具有以下特点: 1. 界面友好:由于采用了QT框架开发,系统的界面设计美观、简洁,用户操作方便易懂。 2. 功能全面:该系统包含了考试的各个环节,包括试题管理、考生管理、成绩统计等功能。考试管理员可以方便地添加、编辑、删除试题,管理考生信息以及查看成绩统计等。 3. 安全可靠:系统采用了安全性较高的数据加密技术,考试过程中的信息传输和存储都得到了保护,确保考试的安全性和可靠性。 4. 灵活易用:系统具有较好的灵活性,可以根据不同考试的需要进行定制和配置,同时用户界面简洁易用,学生和教师可以轻松地操作和管理。 5. 效率高:系统具备较高的处理速度和并发性能,可以同时支持多个考试场次,保证考试的效率和稳定性。 6. 开源方便:因为是开源项目,所以可以根据自己的需求进行二次开发和定制,也可以参与社区的讨论和交流,共同完善项目,满足更多用户的需求。 总之,QT C考试系统作为一个开源项目具备了界面友好、功能全面、安全可靠、灵活易用、效率高的特点,同时还具有开放性和可扩展性,为教育行业提供了一种方便、高效的在线考试解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值