1. 程式人生 > >QT 製作隨機點名器

QT 製作隨機點名器

一、簡介

二、UI介面設計、讀txt檔案

三、QTimer定時器、隨機數

四、不重複點名

五、原始碼


一、簡介

上學時某老師用點名器隨機點名,現在就來製作一個點名器。編寫隨機點名器,主要有以下幾個步驟:

ui介面設計  --》  讀取data.txt檔案中的姓名資訊   --》  QTimer定時器定時觸發生成隨機數的函式   --》   設定點名策略為不重複點名。

在原始檔目錄下新增 data1.txt 記錄所有同學的姓名;

內容如下(本例中有40個名字):

最終結果如下:


二、UI介面設計、讀txt檔案

      1.  新建mainWindow專案,專案名為“Rand_select”。雙擊.ui檔案,在ui介面下設計主視窗為如下形式:1

 拖入一個TextEdit(用於顯示文字資訊)、兩個PushButton空間(用於觸發和暫停QTimer定時器)。“開始”按鈕物件名設定為start_Btn,暫停按鈕物件名設定為stop_Btn。

      2.讀取data.txt 檔案

在mainwindow.h檔案下MainWindow類下新增成員函式:void  readFile()用於讀取 .txt檔案。

讀取檔案的方法為:使用QTextStream,readAll()將檔案內容全部讀取至QString物件中,最後用空格分割符號將所有名字放到QString陣列中。

void readFile()程式碼如下:

void MainWindow::readFile()
{
    //構造一個以data1.txt為檔名的QFile物件
    QFile file("../Rand_select/data1.txt");
    
    //檔案以只讀方式開啟 || 在讀取時,將行結束符轉換成 \n
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug()<< "open file failure";
        return;
    }
    else
    {
        QString array;
        //建立QTextStream流操作物件,與QFile物件file連線
        QTextStream in(&file);
        //讀取所有文字
        array = in.readAll();
        //trimmed():移除字串兩端空白符,simplified():移除字串兩端的空白字元,
        //使用單個空格字元“ ”代替字串中出現的空白字元。
        array = array.trimmed();
        array = array.simplified();

        int i=0,k=0;
        while(i<array.size())
        {
            //.at(int position):返回當前字元的位置index
            name_data[k] += array.at(i);
            name_data[k]=name_data[k].trimmed();
            if(array.at(i) == " ")
            {
                k++;
            }
            i++;
        }
    }
    file.close();
}

三、QTimer定時器、隨機數

QTimer類為我們提供了一個即可重複觸發又可單次觸發的定時器;

重複觸發,即每隔一段時間(單位是毫秒)就會發射訊號。典型的用法如下:

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(***)); // ***即響應函式
timer->start(1000); // 每隔1000ms

現在在MainWindow類下新增QTimer成員:QTimer *timer = new QTimer;然後在建構函式中新增如下程式碼:

readFile();
connect(timer,SIGNAL(timeout()),this,SLOT(srand()));

響應函式srand()程式碼如下:

void MainWindow::srand()
{
    //QTime(int h,int m, int s, int ms):構造一個具有初始時間的QTime物件
    //.msecsTo(QTime::curentTime()):計算距離當前時間的毫秒數
    //qsrand()使用非固定值來作為種子,希望函式在每次呼叫(間隔大於1ms)時生成的隨機數不一樣。
    qsrand(QTime(0,0,0,0).msecsTo((QTime::currentTime())));
    ui->textEdit->clear();
    int num = qrand()%total;
    ui->textEdit->setText(name_data[num]);
}

四、不重複點名

不重複點名策略為:每當介面暫停按鈕點了一次(即點了一次名),記錄該名字,然後將改名字在QString  array中除去,那麼array元素就減少一個。

開啟ui介面,右鍵“暫停”按鈕,轉到槽,選擇clicked(),槽函式內容如下:

void MainWindow::on_stop_Btn_clicked()
{
    timer->stop();
    
    //num標記上次點名點點到的名字,在QString中的位置
    int num=0;
    QString str = ui->textEdit->toPlainText();
    //total為陣列元素個數,是static全域性變數
    for(int i=0;i<total;i++)
    {
        if(str == name_data[i])
        {
            num = i;
            break;
        }
    }
    for(int i=0;i<total-1;i++)
    {
        if(i>=num)
        {
            name_data[i]=name_data[i+1];
        }
    }
    total--;
}

五、原始碼

//*******************mainwindow.h*******************************

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void readFile();

private slots:
    void on_start_Btn_clicked();
    void srand();
    void on_stop_Btn_clicked();

private:
    Ui::MainWindow *ui;
    QString name_data[41];
    QTimer *timer = new QTimer;
};

#endif // MAINWINDOW_H


//**************************mainwindow.cpp*******************************

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QDebug>
#include <QIODevice>
#include <QTextStream>
#include <QtGlobal>
#include <QTime>

static int total = 41;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    readFile();
    ui->textEdit->setText("點名");
    ui->textEdit->setReadOnly(true);
    connect(timer,SIGNAL(timeout()),this,SLOT(srand()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::readFile()
{
    //構造一個以data1.txt為檔名的QFile物件
    QFile file("../Rand_select/data1.txt");
    
    //檔案以只讀方式開啟 || 在讀取時,將行結束符轉換成 \n
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug()<< "open file failure";
        return;
    }
    else
    {
        QString array;
        //建立QTextStream流操作物件,與QFile物件file連線
        QTextStream in(&file);
        //讀取所有文字
        array = in.readAll();
        //trimmed():移除字串兩端空白符,simplified():移除字串兩端的空白字元,
        //使用單個空格字元“ ”代替字串中出現的空白字元。
        array = array.trimmed();
        //qDebug()<<array;
        array = array.simplified();
        //qDebug()<<array;

        int i=0,k=0;
        while(i<array.size())
        {
            //.at(int position):返回當前字元的位置index
            name_data[k] += array.at(i);
            name_data[k]=name_data[k].trimmed();
            if(array.at(i) == " ")
            {
                k++;
            }
            i++;
        }
    }
    file.close();
}

void MainWindow::on_start_Btn_clicked()
{

        timer->start(100);
}

void MainWindow::on_stop_Btn_clicked()
{
    timer->stop();

    int num=0;
    QString str = ui->textEdit->toPlainText();
    for(int i=0;i<total;i++)
    {
        if(str == name_data[i])
        {
            num = i;
            break;
        }
    }
    for(int i=0;i<total-1;i++)
    {
        if(i>=num)
        {
            name_data[i]=name_data[i+1];
        }
    }
    total--;
}

void MainWindow::srand()
{
    //QTime(int h,int m, int s, int ms):構造一個具有初始時間的QTime物件
    //.msecsTo(QTime::curentTime()):計算距離當前時間的毫秒數
    //qsrand()使用非固定值來作為種子,希望函式在每次呼叫(間隔大於1ms)時生成的隨機數不一樣。
    qsrand(QTime(0,0,0,0).msecsTo((QTime::currentTime())));
    ui->textEdit->clear();
    int num = qrand()%total;
    ui->textEdit->setText(name_data[num]);
}


//**************************main.cpp*******************************


#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.setWindowTitle("點名!");
    w.show();

    return a.exec();
}