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

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

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

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

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

[pastacode lang=»cpp» manual=»class%20emulator%20%3A%20public%20QObject%0A%7B%0A%20%20%20%20Q_OBJECT%0Apublic%3A%0A%20%20%20%20emulator(int%20codesCount%2C%20int%20codeLength%2C%20int%20startCodeIndex%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20int%20startFileCodeIndex%2C%20int%20fileCodeLength%2C%20int%20millisec%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20int%20filesCount%2C%20QString%20catalog)%3B%0A%20%20%20%20~emulator()%3B%0Apublic%20slots%3A%0A%20%20%20%20void%20startEmulating()%3B%0Asignals%3A%0A%20%20%20%20void%20startCodeIndexChanged(int)%3B%0A%20%20%20%20void%20startFileCodeIndexChanged(int)%3B%0A%20%20%20%20void%20logMessage(QString)%3B%0A%20%20%20%20void%20finished()%3B%0Aprivate%20slots%3A%0A%20%20%20%20QString%20addZeros(QString%20str%2C%20int%20strLength)%3B%0A%20%20%20%20QString%20fileName()%3B%0A%20%20%20%20QStringList%20codesList()%3B%0A%20%20%20%20void%20createTimer()%3B%0A%20%20%20%20void%20saveFile()%3B%0A%20%20%20%20void%20continueEmulating()%3B%0Aprivate%3A%0A%20%20%20%20int%20codesCount%3B%0A%20%20%20%20int%20codeLength%3B%0A%20%20%20%20int%20currentCodeIndex%3B%0A%20%20%20%20int%20currentFileCodeIndex%3B%0A%20%20%20%20int%20fileCodeLength%3B%0A%20%20%20%20int%20millisec%3B%0A%20%20%20%20int%20currentfilesCount%3B%0A%20%20%20%20int%20stopFilesCount%3B%0A%20%20%20%20QTimer%20*timer%3B%0A%20%20%20%20QString%20catalog%3B%0A%7D%3B» message=»» highlight=»» provider=»manual»/]

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

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

[pastacode lang=»cpp» manual=»timer%20%3D%20new%20QTimer(this)%3B%0Atimer-%3EsetInterval(millisec)%3B%0Atimer-%3EsetTimerType(Qt%3A%3APreciseTimer)%3B%0Aconnect(timer%2C%20SIGNAL(timeout())%2C%20this%2C%20SLOT(continueEmulating()))%3B%0Atimer-%3Estart()%3B» message=»» highlight=»» provider=»manual»/]

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

[pastacode lang=»cpp» manual=»void%20emulator%3A%3AsaveFile()%0A%7B%0A%20%20%20%20QString%20fName%20%3D%20catalog%2B%22%2F%22%2BfileName()%3B%0A%20%20%20%20QFile%20file(fName)%3B%0A%20%20%20%20QTextStream%20out(%26file)%3B%0A%20%20%20%20if%20(!file.open(QIODevice%3A%3AWriteOnly))%20%7B%0A%20%20%20%20%20%20%20%20emit%20logMessage(tr(%22%D0%9E%D1%88%D0%B8%D0%B1%D0%BA%D0%B0%20%D0%BE%D1%82%D0%BA%D1%80%D1%8B%D1%82%D0%B8%D1%8F%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%20%251%22).arg(fName))%3B%0A%20%20%20%20%20%20%20%20timer-%3Estop()%3B%0A%20%20%20%20%20%20%20%20emit%20finished()%3B%0A%20%20%20%20%7D%0A%09%2F%2F%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F%20codesList()%20%D0%B2%D0%BE%D0%B7%D0%B2%D1%80%D0%B0%D1%89%D0%B0%D0%B5%D1%82%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D1%88%D1%82%D1%80%D0%B8%D1%85-%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2%2C%0A%09%2F%2F%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8B%D0%B2%D0%B0%D0%B5%D0%BC%20%D0%BA%D0%B0%D0%BA%20%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%BD%D1%83%D1%8E%20%D1%81%D1%82%D1%80%D0%BE%D0%BA%D1%83%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20%D0%BF%D0%B5%D1%80%D0%B5%D0%BD%D0%BE%D1%81%20%5Cn%0A%20%20%20%20out%20%3C%3C%20codesList().join(%22%5Cn%22)%3B%0A%09%2F%2F%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%BE%D0%B9%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B5%0A%20%20%20%20emit%20logMessage(fileName())%3B%0A%20%20%20%20currentCodeIndex%2B%3DcodesCount%3B%0A%09%2F%2F%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BE%D0%B1%20%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B8%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%20%D1%81%D1%87%D0%B5%D1%82%D1%87%D0%B8%D0%BA%D0%B0%0A%20%20%20%20emit%20startCodeIndexChanged(currentCodeIndex)%3B%0A%20%20%20%20currentFileCodeIndex%2B%2B%3B%0A%09%2F%2F%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BE%D0%B1%20%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B8%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%20%D1%81%D1%87%D0%B5%D1%82%D1%87%D0%B8%D0%BA%D0%B0%0A%20%20%20%20emit%20startFileCodeIndexChanged(currentFileCodeIndex)%3B%0A%0A%20%20%20%20file.close()%3B%0A%20%20%20%20if%20(%2B%2BcurrentfilesCount%20%3D%3D%20stopFilesCount)%20%7B%0A%20%20%20%20%20%20%20%20timer-%3Estop()%3B%0A%20%20%20%20%20%20%20%20emit%20logMessage(tr(%22%D0%93%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F%20%D0%BE%D0%BA%D0%BE%D0%BD%D1%87%D0%B5%D0%BD%D0%B0%3A%20%D1%81%D1%84%D0%BE%D1%80%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BE%20%251%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20.arg(currentfilesCount))%3B%0A%20%20%20%20%20%20%20%20emit%20finished()%3B%0A%20%20%20%20%7D%0A%7D» message=»» highlight=»» provider=»manual»/]

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

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

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

[pastacode lang=»cpp» manual=»emulator%20*emul%20%3D%20new%20emulator(ui-%3EcodesCount-%3Evalue()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ui-%3EcodeLength-%3Evalue()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ui-%3EstartCodeIndex-%3Evalue()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ui-%3EstartFileCodeIndex-%3Evalue()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ui-%3EfileCodeLength-%3Evalue()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ui-%3Etimeout-%3Evalue()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ui-%3EfilesCount-%3Evalue()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ui-%3Edir-%3Etext())%3B%0AQThread%20*thrd%20%3D%20new%20QThread%3B%0Aemul-%3EmoveToThread(thrd)%3B%0A%2F%2F%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%20%D0%BE%D0%BA%D0%BE%D0%BD%D1%87%D0%B0%D0%BD%D0%B8%D1%8F%20%D1%84%D0%BE%D1%80%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%20%D1%81%D0%B8%D0%B3%D0%BD%D0%B0%D0%BB%20%D0%B4%D0%BB%D1%8F%20%D0%B7%D0%B0%D0%B2%D0%B5%D1%80%D1%88%D0%B5%D0%BD%D0%B8%D1%8F%20%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B%20%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0%0Aconnect(emul%2C%20SIGNAL(finished())%2C%20thrd%2C%20SLOT(quit()))%3B%0A%2F%2F%D1%81%D0%B8%D0%B3%D0%BD%D0%B0%D0%BB%20%D0%BD%D0%B0%20%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%B0%20%D1%8D%D0%BC%D1%83%D0%BB%D1%8F%D1%82%D0%BE%D1%80%D0%B0%0Aconnect(thrd%2C%20SIGNAL(finished())%2C%20emul%2C%20SLOT(deleteLater()))%3B%0A%2F%2F%D0%BD%D0%B0%D1%87%D0%B0%D0%BB%D0%BE%20%D1%8D%D0%BC%D1%83%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%0Aconnect(thrd%2C%20SIGNAL(started())%2C%20emul%2C%20SLOT(startEmulating()))%3B%0A%2F%2F%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%B0%D1%87%D0%B0%20%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%B4%D0%BB%D1%8F%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8%20%D0%B2%20%D0%BB%D0%BE%D0%B3%0Aconnect(emul%2C%20SIGNAL(logMessage(QString))%2C%20this%2C%20SLOT(logMessage(QString)))%3B%0A%2F%2F%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5%20%D1%82%D0%B5%D0%BA%D1%83%D1%89%D0%B5%D0%B3%D0%BE%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D0%B0%20%D0%BA%D0%BE%D0%B4%D0%B0%0Aconnect(emul%2C%20SIGNAL(startCodeIndexChanged(int))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20this%2C%20SLOT(startCodeIndexChanged(int)))%3B%0A%2F%2F%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5%20%D1%82%D0%B5%D0%BA%D1%83%D1%89%D0%B5%D0%B3%D0%BE%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D0%B0%20%D0%BA%D0%BE%D0%B4%D0%B0%20%D0%B2%20%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%0Aconnect(emul%2C%20SIGNAL(startFileCodeIndexChanged(int))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20this%2C%20SLOT(startFileCodeIndexChanged(int)))%3B%0A%2F%2F%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA%0Athrd-%3Estart()%3B» message=»» highlight=»» provider=»manual»/]

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

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

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

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

Портфолио

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

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