QML for Android 实现二维码扫描(QZXing)

前言

由于项目要求,需要用 Qt 做一个Android 程序用于扫描二维码并获取扫码内容,之前参考了很多资料,很多都是基于桌面端的二维码识别,如一去丶二三里大神的Qt之二维码扫描,原理是直接导入一张二维码图片然后进行识别,而移动端会稍微麻烦一点点,并且关于 Qt 来做一个 Android 程序扫描二维码的资料太少,最终通过各种尝试,采用 QML+QZXing 的结合来实现该功能,这里做一个简单的总结。

原理

程序实现原理大概分为几个步骤:

1.Camera启动手机摄像头
2.VideoOutput获取一个摄像头的预览视频帧
3.QZXing对视频帧进行解析并返回内容

效果图

界面做得很简陋,但是功能实现,后期只要提供界面图标来重新实现界面就完美了。

左边是程序界面,中间的扫描线是动态的,右边是扫描后的效果,content 是扫描到的二维码内容,Detected count是检测次数。

源码

来看看 QML 端关键的代码

import QtQuick 2.6
import QtQuick.Window 2.0
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.1
import QtMultimedia 5.5
import QZXing 2.3

ApplicationWindow
{
    id: window
    visible: true
    width: 1080
    height: 1920
    title: "Qt QZXing Filter Test"

    property int detectedTags: 0
    property string lastTag: ""
    property  int  nWidth: Math.min(width,height)

    Rectangle
    {
        id: bgRect
        color: "white"
        anchors.fill: videoOutput
    }

    Label
    {
        id: text1
        wrapMode: Text.Wrap
        color:"white"
        z: 50
        text: "Detected count: " + detectedTags
    }

    Camera
    {
        id:camera
        focus {
            focusMode: CameraFocus.FocusContinuous
            focusPointMode: CameraFocus.FocusPointAuto
        }
    }

    VideoOutput
    {
        id: videoOutput
        source: camera
        anchors.fill: parent
        autoOrientation: true
        fillMode: VideoOutput.Stretch
        filters: [ zxingFilter ]
        MouseArea {
            anchors.fill: parent
            onClicked: {
                camera.focus.customFocusPoint = Qt.point(mouse.x / width,  mouse.y / height);
                camera.focus.focusMode = CameraFocus.FocusMacro;
                camera.focus.focusPointMode = CameraFocus.FocusPointCustom;
            }
        }
        Rectangle {
            id: captureZone
            width: nWidth*0.6
            height: width
            anchors.centerIn: parent
            color:"transparent"
            border.color: "lightgreen"
            border.width: 3

            Rectangle{
                id:line
                width: parent.width*0.9
                height: 12
                color: "lightgreen"
                anchors.horizontalCenter: parent.horizontalCenter
                radius: 8

                PropertyAnimation{
                    id:ani
                    target:line
                    properties: "y"
                    duration: 1500
                    from:0
                    running: true
                    to:captureZone.height
                    onStopped: {
                        y=0
                        ani.start()
                    }
                }
            }

        }
    }

    QZXingFilter
    {
        id: zxingFilter
        captureRect: {
            // setup bindings
            videoOutput.contentRect;
            videoOutput.sourceRect;
            //识别的区域,这里稍微比扫描框大一些
            return videoOutput.mapRectToSource(videoOutput.mapNormalizedRectToItem(Qt.rect(
                0.2, 0.2, 0.6, 0.6
            )));
        }

        decoder {
            enabledDecoders: QZXing.DecoderFormat_EAN_13 | QZXing.DecoderFormat_CODE_39 | QZXing.DecoderFormat_QR_CODE

            onTagFound: {
                console.log(tag + " | " + decoder.foundedFormat() + " | " + decoder.charSet());

                window.detectedTags++;
                window.lastTag = tag;
            }

            tryHarder: false
        }

        onDecodingStarted:
        {
            console.log("started");
        }

        property int framesDecoded: 0
        property real timePerFrameDecode: 0

        onDecodingFinished:
        {
           timePerFrameDecode = (decodeTime + framesDecoded * timePerFrameDecode) / (framesDecoded + 1);
           framesDecoded++;
           console.log("frame finished: " + succeeded, decodeTime, timePerFrameDecode, framesDecoded);
        }
    }

    Label
    {
        wrapMode: Text.Wrap
        color:"white"
        anchors.bottom: parent.bottom
        z: 50
        text: "content: " + lastTag
    }
}

权限

在 Android 上运行,开启摄像头需要先添加权限,在 AndroidManifest.xml文件中添加:

<uses-permission android:name="android.permission.CAMERA"/>

关于 QZXing

QML 中用到的二维码解码库,需要去官网下载源码并导入到工程中, 官网:QZXing ,详情请参考官网介绍,这里不再赘述。

猜你喜欢

转载自blog.csdn.net/luoyayun361/article/details/80304874
今日推荐