QtQuick框架下制作的蓝牙控制App,包括了QtQuick Control的Material样式设置、使用Loader的页面切换、QtBluetooth的使用,定时器的使用

BB

这次嵌入式,因为看错题,以为App需要自己做,然后又从来没有开发过Android App,又不熟悉Java,学习+开发的时间最多又只有一天,咋办呢?最后蒟蒻选择了QtQuick做成了跨平台App,从学习到开发用了不到一天的时间,说明入门学习成本不高,实现还ok。
本文不会给出整个项目代码,只记录一些特定功能的实现。

Introduction

本文主要介绍了蒟蒻使用QtQuick制作通过蓝牙连接蓝牙模块App中的核心步骤,包括了QtQuick Control的Material样式设置、使用Loader的页面切换、QtBluetooth的使用,定时器的使用。
蒟蒻写的应该有许多bug,建议各位dalao还是要看看Qt官方文档 orz
另外写完本文会有一段时间不会更新的,要综合训练了暂时不啃新点

Hint

本节记录了一些在开发过程中遇到的坑点。 编译到Windows下运行:

编译到Android下运行:

与Qt自身有关的:


Environment


Functions

Material Design样式
Material Design样式QtQuick Control的版本至少为2
在pro文件中加入

QT += quickcontrols2

在main.cpp文件中加入

QQuickStyle::setStyle("Material");

在ApplicationWindow中加入,就可以指定主题了

Material.theme: Material.Light
Material.accent: Material.Blue


Loader页面切换
如果在桌面端开发,程序小的话页面切换其实不是刚需,但是因为这次要照顾Android,所以需要进行页面切换。
实现页面切换只需要改变Loader.source即可。

Loader {
    id: ld
    anchors.fill: parent
    source: "startPage.qml"
}

因为Loader切换时,位于source的qml中的组件会全部GG,所以程序小的话可以开一个全局的qml,然后在里面放Loader和各种全局组件。项目大的话应该有更好的方法,时间紧迫没研究过。

QtBluetooth
要连接蓝牙设备需要用到BluetoothDiscoveryModel用于搜索蓝牙设备,BluetoothSocket用于蓝牙设备间的连接、数据传输等。
项目中BluetoothDiscoveryModel的代码如下。其中discoveryModeBluetoothDiscoveryModel.DeviceDiscovery是搜索设备,为BluetoothDiscoveryModel.FullServiceDiscoveryBluetoothDiscoveryModel.MinimalServiceDiscovery为搜素蓝牙服务。
由于BluetoothDiscoveryModel.DeviceDiscovery可以申请位置权限,实现蓝牙搜索,而蒟蒻又不会手写申请权限,所以蒟蒻的策略是先使用BluetoothDiscoveryModel.DeviceDiscovery,待到按钮触发时才改为BluetoothDiscoveryModel.MinimalServiceDiscovery
搜索到新设备时,会触发onServiceDiscovered,这时蒟蒻的策略是匹配MAC地址,匹配ok就传递给socket。

BluetoothDiscoveryModel {
    id: btModel
    running: true
    property bool isFound: false
    discoveryMode: BluetoothDiscoveryModel.DeviceDiscovery

    onErrorChanged: {
        if (error != BluetoothDiscoveryModel.NoError) {
            console.log(error)
        }
    }

    onServiceDiscovered: {
        if(!isFound && service.deviceAddress == string_macAddress) {
            console.log("Found new service " + service.deviceAddress + " " + service.deviceName + " " + service.serviceName);
            socket.setService(service)
            isFound = true
        }
    }
}

项目中BluetoothSocket的代码如下。当连接时,会触发BluetoothSocket.Connected,此时再把BluetoothDiscoveryModel关了,不传递时就关闭是因为还未连接,关闭会有bug出现!
当断开时,会触发BluetoothSocket.Unconnected
目标设备发送内容,会触发onStringDataChanged;要向目标设备发送内容,只需要更改socket.stringData的内容即可。

BluetoothSocket {
    id: socket
    connected: true

    onSocketStateChanged: {
        switch (socketState) {
        case BluetoothSocket.Unconnected:
            //...
            break;
        case BluetoothSocket.Connected:
            console.log("Connected to server");
            btModel.running = false
            ld.source = "gamePage.qml"
            break
        }
    }
    onStringDataChanged: {
        let data = socket.stringData
        console.log(data)
        //...
    }
}


定时器Timer
需要使用定时器是因为长按按钮需要不断向设备发送消息,而Qt无法处理。这时候可以改成,按下按钮时打开定时器,松开按钮时停止定时器。
项目中一个定时器的代码如下所示。triggeredOnStart为一打开就生效,repeat为是否重复,onTriggered为每次需要做的内容。

Timer {
    id: timer_backward
    interval: 70
    repeat: true
    running: false
    triggeredOnStart: true
    onTriggered: {
        socket.stringData = "2"
    }
}