在Qt5的QML中使用QZXing識別二維碼

前言

ZXing庫是一個用來識別二維碼的庫,QZXing是一個基於Qt的Qt wrapper library,在本文咱們使用它和qml開發一個android小應用。android

添加QZXing項目

QZXing最經常使用是做爲一個子項目包含在咱們的項目中,在咱們的項目的pro文件中添加以下的一句:後端

include(./QZXing/QZXing.pri)

QZXing和咱們的pro文件在同一個目錄。markdown

qml程序

import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QZXing 2.3

ApplicationWindow {
    title: qsTr("Hello World")
    width: 640
    height: 480
    visible: true

    property real dpi: Screen.pixelDensity.toFixed(2)

    menuBar: MenuBar {
        Menu {
            title: qsTr("&File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: messageDialog.show(qsTr("Open action triggered"));
            }
            MenuItem {
                text: qsTr("E&xit")
                onTriggered: Qt.quit();
            }
        }
    }


    Image {
        id: qr_code
        source: "qrc:/image/qrcode.png"
        height: 20 * dpi
        width: 20 * dpi
        fillMode: Image.PreserveAspectFit
        anchors {top:parent.top; topMargin: 2 * dpi;horizontalCenter: parent.horizontalCenter}

    }

    Button {
        text: qsTr("O")
        height: 10 * dpi
        anchors {top:qr_code.bottom; topMargin: 2 * dpi; left:parent.left; leftMargin: 2 * dpi;
            right:parent.right; rightMargin: 2 * dpi}
        onClicked: {
            decoder.decodeImageQML(qr_code)
        }
    }

    QZXing {
        id:decoder
        enabledDecoders: QZXing.DecoderFormat_QR_CODE
        onDecodingStarted: {
            console.log("QZXing decode start!")
        }

        onDecodingFinished: {
            if (succeeded) {
                console.log("success")
            } else {
                console.log("fail")
            }
        }

        onTagFound: {
            messageDialog.show("QR_CODE:" + tag)
        }




    }



    MessageDialog {
        id: messageDialog
        title: qsTr("May I have your attention, please?")

        function show(caption) {
            messageDialog.text = caption;
            messageDialog.open();
        }
    }

}

而後咱們編譯咱們的程序。這是QZXing會報兩個錯誤。
1.在CameraImageWrapper.cpp文件的147行app

#if __cplusplus > 199711L
        memcpy(m, tmpRow->values()..data(), width);
#else
        memcpy(m, &tmpRow->values()[0], width);
#endif

刪除一個點就好了
2.可能個人編譯環境中沒有iconv.h文件,我在pro文件添加以下解決函數

DEFINES += NO_ICONV

這樣咱們的程序就編譯經過了。測試

QML Image to QImage

而後咱們測試,沒有失敗二維碼,我調試進decodeImageQML函數,這句ui

 QGraphicsObject *item = qobject_cast<QGraphicsObject*>(imageObj);

失敗,item爲NULL,沒有轉化成功。
上網找資料發現,是在Qt5如下版本能夠運行。而後看見Qt5開始QML後端實現不一樣了。而後我看Qt5的文檔,發現QML中的Item是QQuickItem類的實例,繼承自QObject 和 QQmlParserStatus。在Qt4.8中,QML的Item是QDeclarativeItem的實例,而QDeclarativeItem繼承於QGraphicsObject和QDeclarativeParserStatus,因此在qt5如下版本能夠運行,而Qt5就不行了。QQuickItem有一個window函數其然回Item渲染的窗體,其是一個QQuickWindow對象,而QQuickWindow有一個gradWindow函數,其描述以下:
Grabs the contents of the window and returns it as an image.
因此我修改了ImageHandler::extractQImage函數spa

QImage ImageHandler::extractQImage(QObject *imageObj,
                                   const double offsetX, const double offsetY,
                                   const double width, const double height)
{
#if QT_VERSION >= 0x050000
    QQuickItem *item = qobject_cast<QQuickItem*>(imageObj);
#else
    QGraphicsObject *item = qobject_cast<QGraphicsObject*>(imageObj);
#endif
    if (!item) {
        qDebug() << "Item is NULL";
        return QImage();
    }
#if QT_VERSION >= 0x050000
    QQuickWindow *window = item->window();
    QImage img = window->grabWindow();
#else
    QImage img(item->boundingRect().size().toSize(), QImage::Format_RGB32);
    img.fill(QColor(255, 255, 255).rgb());
    QPainter painter(&img);
    QStyleOptionGraphicsItem styleOption;
    item->paint(&painter, &styleOption);
#endif

    if(offsetX == 0 && offsetY == 0 && width == 0 && height == 0)
        return img;
    else
    {
        return img.copy(offsetX, offsetY, width, height);
    }
}

OK,識別成功,有圖爲證
這裏寫圖片描述調試

忘了
在QML中使用QZXing,須要在main函數中註冊一下code

#include <QApplication>
#include <QQmlApplicationEngine>
#include "QZXing.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QZXing::registerQMLTypes();

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}
相關文章
相關標籤/搜索