C++, Qt, Портфолио

Эмулятор работы инспектора машинного зрения (формирование выходных файлов)

При написании одного проекта мне необходимо обрабатывать файлы, формируемые на основании полученных данных от инспектора машинного зрения. Содержимое файла — список штрих-кодов определенного количества, наименование файла — <год месяц день>_<штрих-код короба>. Эти файлы сохраняются в определенном каталоге,  а формируются с периодичность N миллисекунд. Для тестирования приложения мне необходимо написать эмулятор такого «инспектора». Приложение будет формировать файлы со списком штрих-кодов и сохранять в заданный каталог.

главное окно эмулятора

Основной класс, отвечающий за работу эмулятора выглядит таким образом:

class emulator : public QObject
{
    Q_OBJECT
public:
    emulator(int codesCount, int codeLength, int startCodeIndex,
             int startFileCodeIndex, int fileCodeLength, int millisec,
             int filesCount, QString catalog);
    ~emulator();
public slots:
    void startEmulating();
signals:
    void startCodeIndexChanged(int);
    void startFileCodeIndexChanged(int);
    void logMessage(QString);
    void finished();
private slots:
    QString addZeros(QString str, int strLength);
    QString fileName();
    QStringList codesList();
    void createTimer();
    void saveFile();
    void continueEmulating();
private:
    int codesCount;
    int codeLength;
    int currentCodeIndex;
    int currentFileCodeIndex;
    int fileCodeLength;
    int millisec;
    int currentfilesCount;
    int stopFilesCount;
    QTimer *timer;
    QString catalog;
};

Генерация файлов происходит по срабатыванию таймера и заканчивается, когда сформировано указанное в начальных значениях количество файлов.

Создание и запуск таймера:

timer = new QTimer(this);
timer->setInterval(millisec);
timer->setTimerType(Qt::PreciseTimer);
connect(timer, SIGNAL(timeout()), this, SLOT(continueEmulating()));
timer->start();

Объект timer удаляется при удалении объекта класса emulator. Тип таймера Qt::PreciseTimer отвечает за точность срабатывания до миллисекунды, как нам и необходимо. Слот continueEmulating() вызывает слот saveFile():

void emulator::saveFile()
{
    QString fName = catalog+"/"+fileName();
    QFile file(fName);
    QTextStream out(&file);
    if (!file.open(QIODevice::WriteOnly)) {
        emit logMessage(tr("Ошибка открытия файла %1").arg(fName));
        timer->stop();
        emit finished();
    }
	//функция codesList() возвращает список штрих-кодов,
	//записываем как объединенную строку через перенос \n
    out << codesList().join("\n");
	//сообщение основной программе
    emit logMessage(fileName());
    currentCodeIndex+=codesCount;
	//сообщение об изменении значения счетчика
    emit startCodeIndexChanged(currentCodeIndex);
    currentFileCodeIndex++;
	//сообщение об изменении значения счетчика
    emit startFileCodeIndexChanged(currentFileCodeIndex);

    file.close();
    if (++currentfilesCount == stopFilesCount) {
        timer->stop();
        emit logMessage(tr("Генерация окончена: сформировано %1 файлов")
                        .arg(currentfilesCount));
        emit finished();
    }
}

Сигнал finished() посылается управляющему потоку для завершения операции и удаления объектов.

Создание объектов и запуск работы

После задания пользователем начальных значений, он нажимает на кнопку ОК и программа начинает работу. Для этого необходимо создать все объекты (эмулятора и потока):

emulator *emul = new emulator(ui->codesCount->value(),
                                  ui->codeLength->value(),
                                  ui->startCodeIndex->value(),
                                  ui->startFileCodeIndex->value(),
                                  ui->fileCodeLength->value(),
                                  ui->timeout->value(),
                                  ui->filesCount->value(),
                                  ui->dir->text());
QThread *thrd = new QThread;
emul->moveToThread(thrd);
//после окончания формирования файлов сигнал для завершения работы потока
connect(emul, SIGNAL(finished()), thrd, SLOT(quit()));
//сигнал на удаление объекта эмулятора
connect(thrd, SIGNAL(finished()), emul, SLOT(deleteLater()));
//начало эмулирования
connect(thrd, SIGNAL(started()), emul, SLOT(startEmulating()));
//передача сообщения для записи в лог
connect(emul, SIGNAL(logMessage(QString)), this, SLOT(logMessage(QString)));
//изменение текущего значения индекса кода
connect(emul, SIGNAL(startCodeIndexChanged(int)),
            this, SLOT(startCodeIndexChanged(int)));
//изменение текущего значения индекса кода в имени файла
connect(emul, SIGNAL(startFileCodeIndexChanged(int)),
            this, SLOT(startFileCodeIndexChanged(int)));
//запуск
thrd->start();

Слот startEmulating() создает и запускает таймер.

Проект находится в открытом доступе на BitBucket.

Возможно, вам будет интересно взглянуть на мой другой проект в открытом доступе: DBRecordWidget — Библиотека-виджет для работы с данными.

Чтобы заказать проект или получить консультацию, перейдите, пожалуйста, на страницу Контакты.

Портфолио

Оставьте своё мнение...

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.