基於Qt實現駕校科目考試系統的示例代碼
1.設置登錄界面
LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog) { ui->setupUi(this); ui->imgLabel->setScaledContents(true);//設置填充 this->resize(ui->imgLabel->width(),ui->imgLabel->height());//設置窗口大小 //設置窗口標題 this->setWindowTitle(("駕校科目一考試登錄")); //設置窗口風格 this->setWindowFlags(Qt::Dialog |Qt::WindowCloseButtonHint); }
2.登錄功能實現
2.1驗證郵箱地址
首先判斷輸入的賬號是否符合郵箱格式 ,如果符合則進行登錄驗證,否則提示格式錯誤
void LoginDialog::on_loginButton_clicked() { //首先通過正則表達式判斷賬號是否是一個合法的郵箱格式 //^:表示規則字符串開始、$:表示規則字符串的結束 //+:表示匹配次數≥1次、*:表示匹配任意次數(可為0次) {n,m}表示匹配次數最少n次 最多m次 QRegExp rx("^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$");//初始化時指定規則字符串 bool res = rx.exactMatch(ui->accountEdit->text());//對用戶輸入的賬號進行匹配 if(res){//匹配成功 QMessageBox::information(this,"提示","歡迎登錄科目一考試科目系統"); }else{//匹配不成功 QMessageBox::information(this,"提示","非法郵箱地址!請您重新輸入"); ui->accountEdit->clear();//清空賬號輸入框 ui->codeEdit->clear();//清空密碼輸入框 ui->accountEdit->setFocus();//賬號輸入框聚焦 return ; } }
2.2賬號密碼登錄
當賬號格式合法後,讀取保存賬號和密碼的文檔進行匹配
if(res){//匹配成功 //QMessageBox::information(this,"提示","歡迎登錄科目一考試科目系統"); QString filename;//文件路徑 QString AccInput;//用戶輸入賬號 QString strCode;//用戶輸入密碼 QString strLine;//每次讀取一行數據 QStringList strList;//分割讀取一行數據 filename="../account.txt";//設置文件路徑 AccInput=ui->accountEdit->text();//獲取賬號 strCode=ui->codeEdit->text();//獲取密碼 QFile file(filename);//初始化 QTextStream stream(&file);//文本類型文件流 //指定隻讀方式打開,指定文件類型式文本類型 if(file.open(QIODevice::ReadOnly|QIODevice::Text)){ //打開成功 while(!stream.atEnd()){ strLine=stream.readLine();//每次讀取一行 strList = strLine.split(",");//將讀取到的行按","分割 if(AccInput==strList.at(0)){ if(strCode==strList.at(1)){ //賬號和密碼匹配成功 QMessageBox::information(this,"提示","歡迎進入科目一考試系統"); file.close(); return ; }else{ //賬號匹配成功&密碼不成功 QMessageBox::information(this,"提示","密碼錯誤!請重新輸入!"); ui->codeEdit->clear(); ui->codeEdit->setFocus(); file.close(); return ; } } } QMessageBox::information(this,"提示","輸入賬號有誤!請重新輸入!"); ui->accountEdit->clear();//清空賬號輸入框 ui->codeEdit->clear();//清空密碼輸入框 ui->accountEdit->setFocus();//賬號輸入框聚焦 file.close(); return; }
2.3密碼隱藏
將密碼控件的echoMode屬性值改為Password即可
3.考試界面開發
3.1考試用時
首先添加一個考試對話框類;在考試對話框類中添加QTimer和int屬性用於表示計時器和已用時;設定計時器的時間間隔為1s,通過connect函數將計時器與已用時顯示信號槽連接起來
examDialog.h
#ifndef EXAMDIALOG_H #define EXAMDIALOG_H #include<QDialog> #include<QTimer> class ExamDialog : public QDialog { Q_OBJECT//使用信號槽 public: ExamDialog(QWidget* parent=0); void initTimer(); private: QTimer*m_timer;//計時器 int m_timeGo;//考試已用時 private slots: //私有槽方法 void freshTime(); }; #endif // EXAMDIALOG_H
examDialog.cpp
#include "examdialog.h" ExamDialog::ExamDialog(QWidget* parent):QDialog(parent) { setWindowTitle("考試已用時:0分0秒"); initTimer(); } void ExamDialog::initTimer() { m_timeGo=0; m_timer=new QTimer(this); m_timer->setInterval(1000);//設置計時器時間間隔1s m_timer->start();//啟動計時器 //通過connect方法,連接信號槽。m_timer每發送timeout()信號時,由this執行槽方法freshTime() connect(m_timer,SIGNAL(timeout()),this,SLOT(freshTime())); } void ExamDialog::freshTime() { //刷新考試用時 m_timeGo++; QString min=QString::number(m_timeGo/60);//計算分鐘,將整數轉QString QString sec=QString::number(m_timeGo%60); setWindowTitle("考試已用時:"+min+"分"+sec+"秒"); }
3.2題目佈局
添加屬性以及初始化方法
public: void initLayout(); //初始化佈局管理器 bool initTextEdit();//初始化文本編輯器 void initButton(); //初始化按鈕及標簽 private: QTextEdit*m_textEdit; //考試題庫顯示 QLabel*m_titleLabels[10]; //題目標簽 QRadioButton *m_radioBtns[32];//單選按鈕 QCheckBox *m_checkBtn[4]; //多選題按鈕 QRadioButton *m_radioA; //判斷題A選項 QRadioButton *m_radioB; //判斷題B選項 QGridLayout*m_layout; //佈局管理器 QStringList m_answerList; //答案
在initLayout函數中,設置當前窗口為為管理器父窗口,規定控件間的距離以及控件和窗體間的距離
void ExamDialog::initLayout() { //以當前窗口作為父窗口 m_layout=new QGridLayout(this); m_layout->setSpacing(10);//設置控件之間的間距 m_layout->setMargin(10);//設置窗體與控件鍵的邊距 }
在initTextEdit函數中,讀取文本中的題目信息並將答案行單獨存儲,將讀取到的題目信息顯示在控件中,並將控件交給佈局管理器在窗體上佈局。
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; }else if((nLines%6==0&&nLines>=6&&nLines<=6*9)||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; } }
在初始化函數中對窗體背景和字體進行一些設置
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()){ }else{ //讀取失敗 QMessageBox::information(this,"提示","初始化題庫數據文件失敗!"); //當前應用程序立刻響應槽方法quit QTimer::singleShot(0,qApp,SLOT(quit())); } }
3.3按鈕佈局
佈局方法就是先將控件初始化,然後交給佈局管理器進行佈局。但要註意的是單選按鈕的分組:每個單選題的四個按鈕為一組,判斷題的兩個按鈕為一組
新添加QbuttonGroup屬性
private: QButtonGroup* m_btnGroups[9];//單選按鈕分組
在初始換按鈕函數中
void ExamDialog::initButton() { 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); } 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 if(i<8){ //單選題 m_radioBtns[i*4+j]=new QRadioButton(this); m_radioBtns[i*4+j]->setText(strList.at(j)); m_layout->addWidget(m_radioBtns[i*4+j],2+j,i); m_btnGroups[i]->addButton(m_radioBtns[i*4+j]); } } //提交按鈕 QPushButton*submitBtn=new QPushButton(this); submitBtn->setText("提交"); submitBtn->setFixedSize(100,35); m_layout->addWidget(submitBtn,6,9); } }
3.4提交分數
首先將提交按鈕與信號槽連接
connect(submitBtn,SIGNAL(clicked(bool)),this,SLOT(getScore()));
在計算分數前先判斷題目是否全部完成,然後根據讀取的答案計算分數
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 checkSelect=0; for(int i=0;i<4;++i){ if(m_checkBtns[i]->isChecked()){ checkSelect++; } } //多選題未選或隻選瞭一個也算未完成 if(checkSelect==0||checkSelect==1){ return true; } //判斷題 if(!m_radioA->isChecked()&&!m_radioB->isChecked()){ return true; } return false; } void ExamDialog::getScore() { if(hasNoSelect()){ //有未完成的題目 QMessageBox::information(this,"提示","您有未完成的題目!請完成考試","是"); return ; }else{ //開始統分 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; hasA=answer.contains("A"); hasB=answer.contains("B"); hasC=answer.contains("C"); hasD=answer.contains("D"); 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||hasB!=checkB||hasC!=checkC||hasD!=checkD){ //答案有不一致的 continue; }else{ scores+=10; } } //判斷題統分 if(i==9){ if(m_btnGroups[8]->checkedButton()->text()==m_answerList.at(i)){ scores+=10; } } } int res = QMessageBox::information(this,"提示","您所得分數為:"+QString::number(scores)+"分。是否重新考試?",QMessageBox::Yes|QMessageBox::No); if(res==QMessageBox::Yes){ //重新考試 return; }else{ //不想重新考試 close(); } } }
3.5窗口交互
實現登錄窗口與考試窗口的連接
當用戶登錄成功後通過done函數發送一個Accepted,當用戶點擊取消時發送一個Rejected,然後在主函數中進行判斷
int main(int argc, char *argv[]) { QApplication a(argc, argv); LoginDialog loginDialog; int res = loginDialog.exec(); //以模態方式運行 if(res==QDialog::Accepted){ ExamDialog examDialog; return a.exec(); }else{ return 0; } return a.exec(); }
4.發佈項目
4.1更改編譯路徑
將當前編譯路徑由debug轉為當前文件所在路徑
4.2設置圖標
在項目文件中通過 RC_ICONS加載圖標
RC_ICONS += examsys.ico
圖標已經更改過來瞭
4.3通過dos進行項目打包
將項目由DeBug模式改為Release模式,並編譯
建立一個文件夾作為發佈文件,將Release下生成的.exe文件和需要的文檔拷貝進來
進入要發佈文件夾路徑,然後輸入windeployqt 文件名.exe,點擊回車
打包完成
如果提示 windeployqt不是命令的話需要將安裝的qt的bin路徑添加到環境變量中
到此這篇關於基於Qt實現駕校科目考試系統的示例代碼的文章就介紹到這瞭,更多相關Qt駕校科目考試系統內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!