ZXing庫是一個用來識別二維碼的庫,QZXing是一個基於Qt的Qt wrapper library,在本文咱們使用它和qml開發一個android小應用。android
QZXing最經常使用是做爲一個子項目包含在咱們的項目中,在咱們的項目的pro文件中添加以下的一句:後端
include(./QZXing/QZXing.pri)
QZXing和咱們的pro文件在同一個目錄。markdown
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
這樣咱們的程序就編譯經過了。測試
而後咱們測試,沒有失敗二維碼,我調試進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(); }