用QML开发Android APP(一)

一、需求/目标

用QML已经有一段时间了,我想通过博客记录自己是如何使用QML的,算是写点自己的经验吧,希望对未接触过QML但对它有兴趣的人提供点中文资料,仅此而已。
为了写起来有思路,我们来实现一个能在Android手机上运行的APP,暂且叫这个APP为“135Todo”吧,它是一个待办事项类的软件,类似的现成的软件很多,这类软件最基本的功能应该包含新建事项、标识事项是否完成、删除事项、对事项设置处理时间和优先级。我用过目前很流行的一些APP,但感觉都不是很合个人心意,我很赞同的一点是:“时间管理,不是真的去管理时间,更准确的说应该是效率管理,通过管理来提升做事效率。”软件或手机,它只不过是一个工具,我们用它来计划待办事项,目的是想提高办事效率,所以我们应该把注意力放在事情上面,而不是软件上,所以过于依赖软件功能、花哨界面的话,就显得有点本末倒置了。没有最好的,只有适合自己的,我最近在尝试一种时间管理方法,叫:“1-3-5 Rule”(1-3-5法则,这也是我们要做的APP的名字来源),关于它的详细情况有兴趣请自行google一下,我只简单的介绍,也当是APP的需求点吧:
1、一天中最多处理9件事情,1件最重要的,雷打不动,最多不超过3件次重要的,还有最多不超过5件的琐碎的事。
2、第1点是原则性的但不是强制性的,如果琐碎的事情太多,超过5件也是可以的。如果觉得一天有多件很重要的事情,那么可以指定1件最重要的,其它暂定为次重要的,待最重要的事情完成后,可以把次重要的事情提到最重要的位置。简言之,这样的待办事项列表是很灵活的,当一些事项处理完了并且时间时间允许,自己可以随时增加新的事项进来,而一天也只是一个象征时间,可以是一周或一个月。
3、除了以下描述的3种优先级,还有临时想起的事情、突然冒出的想法、心血来潮的计划,也是常有之事,所以我个人补充了一点,就是可以随时增加这类事项,它的状态是未计划的、未分解的、或有待提上日程的。
通过以上需求,我们的APP看起来可能像这样:
请输入图片描述

新建事项的状态:
请输入图片描述

长按一条事项,事项会变成菜单,可以修改优先级等(模仿了Pocket):
请输入图片描述

二、代码组织

新建工程

1、启动QtCreator,新建项目,选择“Qt Quick Application”,这样代码可以混合C++和QML,基础功能用C++实现,界面和操作在QML完成。
2、工程的构建套件要选择Android for armxxx类型的,请事先在选项->Android下配置好JDK、Android SDK、Android NDK的路径。
注:本文用的QtSDK版本是:qt-opensource-linux-x64-android-5.3.1,5.3.1版本默认生成的代码模板相对以前的版本变得简洁,有些不一样。

混合使用C++和QML

我们使用C++完成数据的读取和保存,有必要的话,还可以做一些与Java层或Android Java SDK交互的事情,这个以后我们再研究。然后,QML专门负责界面布局、用户交互和响应。

C++与QML的交互

  • C++可以调用QML中定义的function,但原则上,我不会这么做,因为很多时候,由QML调用C++接口来完成事情就可以了。两者随意的相互调用会导致软件流程混乱,不易维护。
  • QML可以通过C++对象,获取它的属性和调用它的接口,同时也可以接收它的信号,下面我们也是通过这些方法来完成软件功能的。

首先,我们定义一个C++的类叫TodoCpp,要继承QObject,为QML层提供基础的功能接口,代码:

#ifndef TODOCPP_H
#define TODOCPP_H

#include <QObject>
#include <QSettings> 
class TodoCpp : public QObject
{
    Q_OBJECT
public:
    explicit TodoCpp(QObject *parent = 0);

signals:

public slots:
    //从文件中读出事项列表,并以List方式返回
    QVariantList getItems();

    //把事项列表保存到文件
    void saveItems(const QVariantList& list);

private:
    //使用ini文件来保存待办事项列表
    QSettings* settings;
};

#endif // TODOCPP_H

为了让QML层可以使用C++对象,我们需求在main函数中增加几行代码:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "todocpp.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    //创建对象并暴露给QML,QML可以使用名字todocpp来使用对象
    TodoCpp cpp;
    engine.rootContext()->setContextProperty("todocpp", &cpp); 

    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    return app.exec();
}

C++提供基础服务

  • 数据保存路径:一般情况,我们想保存在存储器上如sdcard,系统不一定有/mnt/sdcard这个目录,所以我们需要使用可移植性更好的方法,我发现最新的Qt版本包含了QStandardPaths这个类,提供了获取系统上各种路径的接口,我们要的就是一个可以保存数据的地方,当APP卸载时,数据不会被删除,因为重装APP后,数据还在,所以我使用了如下的方法来获取这样的路径:
    QString path = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).first();

  • 数据持久化:通常有两种方式:DB和文件,考虑到软件的简单性,直接用ini文件存储待办事项列表(包含每个事项的属性),QSettings这个强大的类,提供了对ini文件的读写操作,构造QSettings的代码如下:
    settings = new QSettings(path.append("/todo1-2-3.ini"), QSettings::IniFormat);
    QSettings还提供了读写一个列表到ini文件的接口,如:
    beginReadArray、setArrayIndex、endArray、beginWriteArray,具体用法见下代码。

  • C++和QML之间的数据传递格式: 我们希望把事项列表存放在一个QList中,并且作为getItems()的返回值,如果QML调用getItems()后,能够直接使用这个list,那是很美好的事情,要知道,QML那里用的是javascript,庆幸的是,真的可以办到,就是使用QVariantMap或QVariantList。所以便有了如下的代码,我们把待办事项一个个转换成QVariantMap,然后所有待办事项再放入QVariantList就可以了,同时我们也约定,从QML传下来的参数,也是同样的格式,代码如下:

    QVariantList TodoCpp::getItems()
    {
        QVariantList list;
    
        int size = settings->beginReadArray("items");
        for (int i = 0; i < size; ++i) {
            settings->setArrayIndex(i);
            QVariantMap m;
            m.insert("text", settings->value("text", "").toString());
            m.insert("pri", settings->value("pri", 99).toInt());
            m.insert("done", settings->value("done", false).toBool());
    
            if(!m.value("text").toString().isEmpty())
                list.push_back(m);
        
  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值