QtとC/C +でデスクトップ用のGUIバーコードリーダーを開発する方法


どのエディションのDynamsoft Barcode SDK 使用すると、基になるアルゴリズムインターフェイスはすべてC/C++で実装されます.DynamSoftのバーコードSDKを正確に評価するには、C +ライブラリから始めましょう.しかし、SDKパッケージで利用できるコマンドラインサンプルのみがあります.私は、それが操作に便利でないので、平野サンプルコードに疲れていました.したがって、私はQtを使用してファンシーGUIバーコードリーダーを書くことにします.この記事では、WindowsとLinuxのためのGUIのバーコードリーダーアプリケーションを開発する方法を示していますQt、mingw、cmake、およびDynamsoft C++バーコードSDK.

バーコードSDKをダウンロード


Dynamsoft C++ SDK v8.6

QTインストール


Windows
訪問Qt Downloads Windows用のQtインストーラをダウンロードします.インストーラは自動的にQtとその依存関係をインストールします.
QtはMingW開発環境を含みますVisual Studio は自動的に検出されません.

私はcmakeとC +のアプリケーションをビルドするために使用されますmsvc Windowsで.しかし、それは重要でありません.私は使用方法を理解するつもりはないmsvc QTプロジェクトのために.代わりに、Windowsアプリケーションを構築するためのGCCを使用して良い試しです.Minwによって提供されるGCCコンパイラを使用するには、Qt\6.1.2\mingw81_64\bin and Qt\Tools\mingw810_64\binPATH 環境変数.
Linux
QtをLinuxでインストールするのはWindowsよりずっと簡単です.
sudo apt-get install qt5-default

WindowsとLinuxのためのcmake設定


使用するQt Creator 迅速にプロジェクトの骨格を設定します.

  • テンプレートの選択Qt Widgets Application .


  • 絹篩で篩うたようCMake ビルドシステムとして.

  • 注意すべきことは、MinLwがリンクをサポートしていることです.リブと.DLLファイル.リンクライブラリを次のように追加できます.
    # DBRx64.lib
    target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets "DBRx64")   
    
    # Or DynamsoftBarcodeReaderx64.dll
    target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets "DynamsoftBarcodeReaderx64")   
    
    
    使用するCMAKE_HOST_WIN32 and CMAKE_HOST_UNIX WindowsとLinuxを区別する.
    if (CMAKE_HOST_WIN32)
        link_directories("${PROJECT_SOURCE_DIR}/platform/windows/bin/") 
    elseif(CMAKE_HOST_UNIX)
        link_directories("${PROJECT_SOURCE_DIR}/platform/linux/")
    endif()
    
    if (CMAKE_HOST_WIN32)
        target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets "DynamsoftBarcodeReaderx64")    
    elseif(CMAKE_HOST_UNIX)
        target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets "DynamsoftBarcodeReader")
    endif()
    
    プロジェクトを構築するには、次の手順を実行します.
    mkdir build
    cd build
    
    ###############################
    # Windows with MinGW
    cmake -G "MinGW Makefiles" ..
    
    # Linux
    cmake ..
    ###############################
    
    cmake --build .
    
    C++クラスを使用する場合CBarcodeReader , あなたはundefined reference Windowsでプロジェクトを構築するときにエラー

    コードをC APIに置き換えると、問題が解決できます.
    reader = DBR_CreateInstance();
    

    デスクトップ用バーコードリーダーの作成


    まず、我々Qt Creator ユーザーインターフェイスのデザイン.

    次に、Qt UIウィジェットをスロット関数に接続しますMainWindow コンストラクタ
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    protected:
        void closeEvent(QCloseEvent *);
    
    private:
        Ui::MainWindow *ui;
        void *reader;
        void showImage(const QImage &image, QString fileName);
        void showMessageBox(QString title, QString content);
    
    private slots:
        void openFile();
        void openFolder();
        void listWidgetClicked(QListWidgetItem *item);
        void exportTemplate();
        void about();
        void setLicense();
        void loadTemplate();
    };
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // Dynamsoft Barcode Reader
        reader = DBR_CreateInstance();
    
        // Open a file.
        connect(ui->actionOpen_File, SIGNAL(triggered()), this, SLOT(openFile()));
    
        // Open a folder.
        connect(ui->actionOpen_Folder, SIGNAL(triggered()), this, SLOT(openFolder()));
    
        // List widget event.
        connect(ui->listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(listWidgetClicked(QListWidgetItem*)));
    
        // Export template.
        connect(ui->actionExport_template, SIGNAL(triggered()), this, SLOT(exportTemplate()));
    
        // About dialog.
        connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
    
        // Set license.
        connect(ui->actionEnter_License_Key, SIGNAL(triggered()), this, SLOT(setLicense()));
    
        // Template load button
        connect(ui->pushButton_template, SIGNAL(clicked()), this, SLOT(loadTemplate()));
    
        // Template export button
        connect(ui->pushButton_export_template, SIGNAL(clicked()), this, SLOT(exportTemplate()));
    }
    
    以下にスロット関数の主な実装を示します:

  • 画像ファイルを読み込みます.
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("Barcode images (*)"));
    if (!fileName.isEmpty()) {
        // Add to list
        ui->listWidget->addItem(fileName);
        ui->statusbar->showMessage(fileName);
    
        // Load the image file to QImage
        QImage image(fileName);
    }
    

  • フォルダーを開き、フォルダ内のすべてのイメージファイルを読み込みます.
    QString folderName = QFileDialog::getExistingDirectory(this, tr("Open Folder"), "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    if (!folderName.isEmpty()) {
        // Get all files in the folder
        QStringList fileNames = QDir(folderName).entryList(QDir::Files | QDir::NoDotAndDotDot);
        // Add to list
        for (int i = 0; i < fileNames.size(); i++) {
            ui->listWidget->addItem(QDir::cleanPath(folderName + QDir::separator() + fileNames.at(i)));
        }
    
        ui->statusbar->showMessage(folderName);
    }
    

  • リストウィジェットのClickイベントをトリガーします.
    void MainWindow::listWidgetClicked(QListWidgetItem *item)
    {
        ui->statusbar->showMessage(QString(item->text()));
    
        // Load the image file to QImage
        QImage image(item->text());
    }
    

  • バーコードイメージをデコードし、結果を表示します.
    void MainWindow::showImage(const QImage &image, QString fileName)
    {
        ui->textEdit_results->setText("");
        if (!image.isNull()) {
            QPixmap pm = QPixmap::fromImage(image);
            QPainter painter(&pm);
            painter.setPen(Qt::red);
    
            /************************
            * Barcode detection.
            ************************/ 
            // Get the template content and initialize the runtime settings.
            QString content = ui->textEdit_results->toPlainText();
            char errorMessage[256];
            DBR_InitRuntimeSettingsWithString(reader, content.toStdString().c_str(), CM_OVERWRITE, errorMessage, 256);
    
            // Set barcode types.
            int types = 0, types2 = 0;
            if (ui->checkBox_code39->isChecked()) {types |= BF_CODE_39;}
            if (ui->checkBox_code93->isChecked()) {types |= BF_CODE_93;}
            if (ui->checkBox_code128->isChecked()){ types |= BF_CODE_128;}
            if (ui->checkBox_codabar->isChecked()){ types |= BF_CODABAR;}
            if (ui->checkBox_itf->isChecked()){ types |= BF_ITF;}
            if (ui->checkBox_ean13->isChecked()){ types |= BF_EAN_13;}
            if (ui->checkBox_ean8->isChecked()){ types |= BF_EAN_8;}
            if (ui->checkBox_upca->isChecked()){ types |= BF_UPC_A;}
            if (ui->checkBox_upce->isChecked()){ types |= BF_UPC_E;}
            if (ui->checkBox_industrial25->isChecked()){ types |= BF_INDUSTRIAL_25;}
            if (ui->checkBox_qrcode->isChecked()){ types |= BF_QR_CODE;}
            if (ui->checkBox_pdf417->isChecked()){ types |= BF_PDF417;}
            if (ui->checkBox_aztec->isChecked()){ types |= BF_AZTEC;}
            if (ui->checkBox_maxicode->isChecked()){ types |= BF_MAXICODE;}
            if (ui->checkBox_datamatrix->isChecked()){ types |= BF_DATAMATRIX;}
            if (ui->checkBox_gs1->isChecked()){ types |= BF_GS1_COMPOSITE;}
            if (ui->checkBox_patchcode->isChecked()){ types |= BF_PATCHCODE;}
            if (ui->checkBox_dotcode->isChecked()){ types2 |= BF2_DOTCODE;}
            if (ui->checkBox_postalcode->isChecked()){ types2 |= BF2_POSTALCODE;}
    
            PublicRuntimeSettings settings;
            DBR_GetRuntimeSettings(reader, &settings);
            settings.barcodeFormatIds = types;
            settings.barcodeFormatIds_2 = types2;
            DBR_UpdateRuntimeSettings(reader, &settings, errorMessage, 256);
    
            int errorCode = DBR_DecodeFile(reader, fileName.toStdString().c_str(), "");
            TextResultArray *handler = NULL;
            DBR_GetAllTextResults(reader, &handler);
    
            if (handler->resultsCount == 0)
            {
                ui->textEdit_results->setText("No barcode found.\n");
                DBR_FreeTextResults(&handler);
                return;
            }
    
            QString out = "";
            TextResult **results = handler->results;
            for (int index = 0; index < handler->resultsCount; index++)
            {
                LocalizationResult* localizationResult = results[index]->localizationResult;
                out += "Index: " + QString::number(index) + "\n";
                out += "Barcode format: " + QString(results[index]->barcodeFormatString) + "\n";
                out += "Barcode value: " + QString(results[index]->barcodeText) + "\n";
                out += "Bounding box: (" + QString::number(localizationResult->x1) + ", " + QString::number(localizationResult->y1) + ") "
                + "(" + QString::number(localizationResult->x2) + ", " + QString::number(localizationResult->y2) + ") "
                + "(" + QString::number(localizationResult->x3) + ", " + QString::number(localizationResult->y3) + ") "
                + "(" + QString::number(localizationResult->x4) + ", " + QString::number(localizationResult->y4) + ")\n";
                out += "----------------------------------------------------------------------------------------\n";
    
                painter.drawLine(localizationResult->x1, localizationResult->y1, localizationResult->x2, localizationResult->y2);
                painter.drawLine(localizationResult->x2, localizationResult->y2, localizationResult->x3, localizationResult->y3);
                painter.drawLine(localizationResult->x3, localizationResult->y3, localizationResult->x4, localizationResult->y4);
                painter.drawLine(localizationResult->x4, localizationResult->y4, localizationResult->x1, localizationResult->y1);
            }
    
            DBR_FreeTextResults(&handler);
    
            painter.end();
            ui->label->setPixmap(pm.scaled(ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    
            ui->textEdit_results->setText(out);
        }
    }
    

  • テンプレートファイルを読み込み、エクスポートします.
    void MainWindow::loadTemplate()
    {
        QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("Barcode Template (*.json)"));
        QFile file(fileName);
        if (file.open(QIODevice::ReadOnly)) {
            QTextStream stream(&file);
            QString content = stream.readAll();
            // DBR_LoadSettingsFromStringPtr(reader, content.toStdString().c_str());
            ui->textEdit_template->setText(content);
        }
    }
    
    void MainWindow::exportTemplate()
    {
        QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("Barcode Template (*.json)"));
        QFile file(fileName);
        if (file.open(QIODevice::ReadWrite)) {
            QTextStream stream(&file);
    
            char* pContent = NULL;
            DBR_OutputSettingsToStringPtr(reader, &pContent, "currentRuntimeSettings");
            stream << QString(pContent);
            DBR_FreeSettingsString(&pContent);
        }
    }
    
  • ここでは、GUIのバーコードリーダーアプリケーションを実行してのスクリーンショットです.

    ソースコード


    https://github.com/yushulx/Qt-desktop-barcode-reader