【qt】考试系统项目

话不多说,先一睹芳颜

咱们的账号,题库和答案都是通过文件获取的.

话不多说,直接开干

目录

一.登录窗口

1.界面设计


这里添加背景图片.

密码输入模式和提示语句.

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

2.邮箱验证

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

3.登录验证

第一行读取的话,要跳过,我们不用.

中间有多个空格,所以我们可以使用正则表达式来进行匹配来获取子串.

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

二.题库窗口

1.考试计时

需要用到计时器

每隔一秒,我们就发出timeout ()这个信号.

然后计算分秒来设置在窗口的标题上.

对窗口进行一点的渲染.

2.布局管理器

这是一个神器,当我们用代码来写组件的时候,有了它,你可以高枕无忧的布局.

下面我们布局组件的时候可以来看布局管理器怎么使用.

3.题库显示


定义了这个来保存我们的答案,方便我们后面计算分数.

添加到组件上,并使用布局管理器.

第一个参数是要添加布局的组件

第二三个参数是这个组件的位置,可以把布局管理器理解成一个表格,从0行0列开始

第四五哥参数是这个组件所占的行数和列数.

4.按钮布局

用的组件数组来初始化.


初始化单选题的时候,我们要进行分组,这样才可以每个题选一项.

同时添加到布局管理器中.

初始化按钮并关联槽函数,来计算分数.

5.计算分数

在计算分数前,我们先来判断是否所有的题都已答完,若没有就继续.

单选题只需要判断每个单选组里面有没有选择的即可.

多选题记一下数,看是不是大于等于2即可

接下来就是正式的算分了.

多选题的算分比较复杂

先获取答案中有那些选项,我们用bool类型来设置状态.

然后与多选框的每个选项状态一一对比.

完全一样才得分.

单选题和判断题都从按钮组中获取到文本来与我们先前获取到的答案进行对比.

显示分数,并给用户选择是否重新答题.

三.窗口交互

现在,我们的两个窗口都写好了,怎么衔接起来呢?

这个可以关闭当前的窗口,并返回一种用户点击的信息.

在main中用模态的方式,来进行接受信息.

并构造我们的考试窗口.

在考试窗口的构造函数中进行显示,以防未初始化窗口就进行显示.

四.完整代码

examdialog.h

cpp 复制代码
#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

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

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_pushButtonLogin_clicked();

    void on_pushButtonCancel_clicked();

private:
    Ui::loginDialog *ui;


    void loginFromFile();
};
#endif // LOGINDIALOG_H

logindialog.cpp

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

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

五.结语

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

完结撒花.

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

相关推荐
andrsted2 小时前
用练题簿小程序 - 让错题不再白错
学习·微信小程序·小程序·学习方法
2601_949950632 小时前
练题簿,把培训从“走过场”变成“真落地”
人工智能·学习·小程序·刷题·小程序推荐
问天_观心6 小时前
大模型微调学习(二)
人工智能·python·深度学习·学习·语言模型·transformer
指掀涛澜天下惊6 小时前
强化学习进阶篇八 策略梯度算法
深度学习·学习·算法·强化学习
star learning white6 小时前
STM32入门学习5
stm32·嵌入式硬件·学习
传奇开心果编程6 小时前
【Rust入门知识点学与练】第4课:条件判断 if / else
开发语言·学习·rust
lifallen7 小时前
Skill 的生命周期:问题消失以后
人工智能·学习·ai·ai编程
千谦阙听7 小时前
C++类和对象(中):默认成员函数、构造与析构、拷贝构造、运算符重载
开发语言·c++·学习
Agudamu11618 小时前
AI 视频学习笔记工具拆解:4款工具谁能把视频变成复习资料
人工智能·学习·音视频
HugoStudio_SWAN8 小时前
洛谷 B4500 / B4449 / B3843 凯撒密码、密码强度与密码合规——加密与安全的三道门
c++·学习·程序人生·算法·安全