在Qt5的QML中使用QZXing识别二维码

来源:互联网 发布:js修改html属性值 编辑:程序博客网 时间:2024/05/29 18:33

前言

ZXing库是一个用来识别二维码的库,QZXing是一个基于Qt的Qt wrapper library,在本文我们使用它和qml开发一个android小应用。

添加QZXing项目

QZXing最常用是作为一个子项目包含在我们的项目中,在我们的项目的pro文件中添加如下的一句:

include(./QZXing/QZXing.pri)

QZXing和我们的pro文件在同一个目录。

qml程序

import QtQuick 2.0import QtQuick.Controls 1.3import QtQuick.Window 2.2import QtQuick.Dialogs 1.2import QZXing 2.3ApplicationWindow {    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行

#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函数,这句

    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函数

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函数中注册一下

#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();}
1 0
原创粉丝点击