ZXing库是一个用来识别二维码的库,QZXing是一个基于Qt的Qt wrapper library,在本文我们使用它和qml开发一个android小应用。
QZXing最常用是作为一个子项目包含在我们的项目中,在我们的项目的pro文件中添加如下的一句:
include(./QZXing/QZXing.pri)
QZXing和我们的pro文件在同一个目录。
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行
#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函数,这句
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();
}
原文地址:http://blog.csdn.net/zhx6044/article/details/44202667