第八章 简易家庭账本——登录

从本章开始,我们预计用七章的篇幅讲解一款信息管理类应用——简易家庭账本,以下简称账本。何谓信息管理类应用?

第一节 概念解释

一、什么是应用

我们称手机、平板电脑(xPad)为便携式智能终端,从本质上说,它们就是可以随身携带的计算机。与这些智能终端相伴而生的,是各种应用商店,App Store、PlayStore、AppMarket等等,用户可以从中获取一些软件,来满足各种各样的需求。这里所说的应用,来自于英文的Application,App是它的简写,指的是应用类的软件,简称应用或应用软件。要想理解一个概念(如“应用”),最好能找到与之相对的概念。在软件行业里,与应用软件相对的是系统软件(system),也就是所谓的操作系统,比如手机的操作系统有安卓、IOS(苹果)、塞班(诺基亚)等,台式电脑的操作系统有windows、linux以及MacOS(苹果)等。

可以把计算机系统(包括智能终端)的组成理解为若干个层,其中最基础的层是硬件(CPU、存储设备以及输入输出设备),硬件之上是操作系统软件,操作系统之上是应用软件,最上层是用户,如图1- 1所示,可见应用软件是最靠近用户的软件。

图8-1 计算机系统的组成

系统软件负责管理硬件,使各个硬件之间可以协同工作,同时为应用软件提供使用环境;应用软件可以满足用户的个性化需求,来完成各种不同的任务。常用的应用软件如word(文字处理)、IE(浏览器)、photoshop(图像处理)、各种游戏软件及输入法软件等等,我们使用的App Inventor开发工具也属于应用软件。如此说来,智能终端上我们自行安装的所有软件都是应用软件,这就是为什么那些提供这类软件的网站自称为“应用商店”。

二、数据库

家庭帐本所属的信息管理类应用,在传统的软件开发行业中,有一个更专业的名字——数据库管理系统。在所谓的信息时代,数据库管理系统在社会生活中扮演着非常重要的角色,大到银行的帐户管理系统、通信公司的计费管理系统、物流公司的运单管理系统,小到一个工厂的进销存管理系统、一家小企业的人事管理系统等等,它们都是数据库管理系统,或者称作信息管理类软件(规模较小的系统)。这些软件几乎渗透到我们日常生活中的每一个角落。随着移动终端的普及,这类软件也在逐渐向移动终端迁移,比如常见的网络银行客户端、微博客户端等等。

无论是哪一种移动应用,只要功能稍微复杂一些,几乎都会涉及到对数据库的操作,数据库也是信息管理类应用的核心技术,因此,我们将简要地介绍一下与数据库有关的知识。

1、数据库分类

数据库,顾名思义,就是存放数据的场所,这些数据有一定的组织结构,永久地保存在存储设备中,便于使用者随时对数据进行操作,并在不同用户之间提供数据的共享。本章所介绍的家庭账本应用,就是利用数据库技术对用户输入的信息进行存储。数据库可分为关系型数据库及非关系型数据库两大类。

关系型数据库适用于那些数据结构相对稳定的信息管理系统,如上面提到的银行、电信等管理系统。你可以把关系型数据库理解为多个相关联的表格,如图8- 1所示,开发上述系统的第一步就是设计数据模型,并依照数据模型建立数据表(带表头的空表格),然后针对这些数据表,使用SQL语言编写程序,实现对数据的增删改查操作。SQL是Structured Query Language(结构化查询语言)的缩写,这种语言的特点是拼字串,专门用于操作关系型数据库。

图8- 2理解关系型数据库

关系型数据库中有两个最基本的概念——字段与记录。图8- 2中的每一个表头称为一个字段,学生成绩单中共有7个字段;每一行称为一条记录,两个表格中各有4条可见的记录。

非关系型数据库也称作NoSQL数据库,其中的SQL就是上面提到的结构化查询语言,非关系型数据库用NoSQL这个名字表示它与关系型数据库之间的差别。你可以将NoSQL数据库想象成一棵树,从树的主干上可以长出任意多的枝干,每个枝干上可以长出任意多个枝条,而每个枝条上可以长出更细的枝条以及任意多个树叶;同时,树叶不仅限于长在枝条上,它们也可以长在主干及枝干上,如图8- 3所示。没有人能够预测树的生长方式,就像没有人能够预测互联网用户的需求一样。

图8- 3理解非关系型数据库(NoSQL)

对于非关系型数据库而言,不太适合使用字段及记录来描述数据,我们使用“数据集合”与“数据项”来描述数据,数据集合中包含数据项,数据项本身可能是数据集合,也可能是单一的值或键值对。

非关系型数据库的流行是最近10年的事情,与社交网络的兴起有很大关系。与关系型数据库相比,这种数据库的特点是不需要事先设计出完整的数据模型,在使用前也无需创建数据表。这种数据库适用于管理那些数据结构及数据类型不固定的信息,也适用于构建那些可生长的系统,即,随时可能增加新功能的系统。著名的社交网站Facebook采用的就是这种类型的数据库。App Inventor中使用的两个数据库组件——本地数据库及网络数据库,均为非关系型数据库。

2、数据库的常规操作——增删改查

无论是关系型数据库,还是非关系型数据库,它们存储及管理的对象都是数据,对数据的操作方法无外乎四大类——增、删、改、查:

  • 增:向关系型数据库的数据表(以下简称数据表)中添加一条或几条新记录,或者向非关系型数据库的数据集合(以下简称数据集合)中增加一个或几个新的数据项;
  • 删:删除数据表中的一条或几条记录,或删除数据集合中的一个或几个数据项;
  • 改:修改数据表中的一条或几条记录,或修改数据集合中的一个或几个数据项;
  • 查:根据给定的条件对数据表或数据集合中的数据进行筛选,并返回筛选结果。

虽然两类数据库都可以进行上述操作,但两者的操作方式有很大差别,就查询操作而言,关系型数据库使用结构化的查询语言(SQL),将一个查询请求提交给数据库服务器,服务器根据查询条件给出查询结果,并返回给请求者,这里最繁重的查询任务是由数据库服务器来完成的。同样,增、删、改的操作也是由数据库服务器来完成。通常我们称服务器端为后端,相对于后端的是前端,前端通常指的是用户所操作的设备,比如个人电脑、智能手机等。对于NoSQL数据库来说,最繁重的任务由前端来完成。当前端设备向NoSQL数据库发出数据请求时,数据库会将整个的数据集合一次性地返回给请求者,这些数据保存在前端设备的内存(变量)中,等待用户的增删改查操作;用户完成对数据的操作后,再将整个数据集合保存到服务器中。这两种技术没有优劣之分,实际上它们各有所长,适用于不同类型的应用。

第二节 App Inventor中的数据库组件

在App Inventor中有两个数据库组件——本地数据库及网络数据库,它们都是NoSQL类型的数据库,它们以“键-值”的方式保存数据,“键”是一个字符串,“值”可以是任意类型的数据,可以是单个的值,如数字、文字、逻辑值等,也可以是列表(不限级数),用户通过“键”来保存与提取数据。当用户使用同一个“键”保存两次数据时,后面的数据将覆盖前面的数据。下面我们利用一组人为编造的收入数据,来介绍App Inentor中的数据库组件,具体说明数据的增删改查方法。数据如图8- 4所示。

图8- 4人为编造的一组收入数据

一、数据的组织

在App Inventor中,数据库组件只能用于存储,数据库本身只能以“标记”来识别数据,而对于“标记”背后的“值”则浑然不知。因此,对数据库内数据的操作,完全依赖于客户端程序,也就是说,如果想要对数据库中的数据进行增删改查操作,必须将数据加载到应用中,保存为列表变量(全局变量或局部变量,视情况而定),然后,针对列表进行操作,最后,再将更新后的列表数据以相同的标记保存到数据库中。这意味着在应用开发过程中,需要大量使用与列表相关的代码块。因此首先我们要学会用列表来表示我们即将处理的数据,如图8- 5所示,我们将图8- 4中的表格转换为App Inventor中的列表。

图8-5 用App Inventor中的列表来组织收入数据

考虑到书籍版面的限制,我们将第2项及第4项折叠起来。这个收入全集列表就是我们未来要处理的数据,我们来分析一下数据的结构。

这是一个3级列表。在第1级列表中,各个列表项的结构完全相同,借用关系型数据库中“记录”的概念,第1级列表中包含了若干条“记录”;第2级列表为键值对列表,其中包含了7个键值对,分别记录了与收入相关的7项信息(日期、收入类别、金额等);第3级列表为键值对,包含两个列表项——键与值。在后续的开发中,无论是收入数据,还是支出数据,都将采用上述格式进行存储,下面来讨论对上述列表的增删改查操作。

二、新增数据项(记录)

与新增操作对应的代码块是“添加(列表)项”块。首先将新增数据组织成一个键值对列表(图8- 5中的第2级列表),然后将该键值对列表添加到收入全集列表中,代码如图8- 6所示。

图8- 6向收入全集列表中新增一条收入记录

三、数据的查询

查询操作的前提是设定查询条件,就收入记录而言,查询条件可以是7个数据项中的任何一项,也可以是两项甚至多项的组合,常见的查询条件中会包含日期、收入类别、收入者等,金额及备忘信息较少可能作为查询条件。在我们的帐本应用中,查询条件是两项信息的组合:日期+任何一个其他项,当其他项为空时,仅按日期进行查询。

查询操作的结果是若干条完整的收入记录,保存在另一个列表变量中(全局或局部),通常将查询结果显示在列表显示框中,以便用户进行选择,并做下一步操作(选中某项后进行删除或修改)。为了显示代码的执行结果,我们创建一个临时项目,在项目中添加一个按钮和一个列表显示框,并将图8- 5及图8- 6中的代码添加到屏幕初始化程序中,如图8- 7所示。

图8-7 创建一个临时项目,并在屏幕初始化程序中设置全局变量

为了节省版面,我们将收入记录的键值对列表折叠起来。现在假设我们要查询2015年2月5日的收入记录,代码如图8- 8所示。查询结果如图8- 9所示。

图8-8 按日期查询
图8-9 按日期查询的结果

以上是针对日期设置的单一查询条件,也可以设置两个查询条件的组合,这需要条件判断时使用“并且”块,例如,查询“2015年赵大同的收入”,代码如图8- 10所示,测试结果如图8- 11所示。

图8-10 为查询设置双重条件
图8-11 双重条件的查询结果

以上是对列表数据的查询,查询条件为单一条件或双重条件,如果有更多的查询条件,只需增加“并且”运算。

为了实现下面的删除操作,图8- 10中将查询结果保存在全局变量中。

四、删除数据项

对数据项的删除要依赖于对数据的查询,满足要求的数据项被显示在列表显示框中,用户可以通过选择其中的某一项,来实现删除操作。代码如图8- 12所示。

图8-12 从数据集合中删除一个数据项

最后以行代码用于更新列表显示框的显示内容,读者可以试试看,如果没有这行代码,结果会怎样。

这里需要格外小心的是,我们的目的是删除收入全集中的数据项,因此要求出选中项在数据全集中的索引值,为此要利用列表显示框的选中项索引值,从查询结果中求出将要删除的项,然后求出该项在收入全集中的位置(索引值),这样才能完成删除操作。

五、修改数据项

与删除操作类似,修改数据项的操作要依赖于对数据的查询,具体代码如图8- 13所示。

图8-13 修改数据集合中的某个数据项

上面例子中我们无论点击列表显示框中的哪一项,结果都是将第一条记录中的17760改为17776,这里我们只是为了说明如何更新列表项,测试结果显示修改操作是成功的。

六、数据的请求与保存

无论是增删改查哪一种操作,首先都要从数据库中读取数据。通常在屏幕初始化时,向数据库请求数据,并在任何一次增删改操作后,将更新后的数据保存到数据库中,代码如图8- 14所示。

图8-14 数据的请求与保存

有两点需要注意:(1)在本地数据库组件的请求数据过程里有两个参数,第一个参数“标记”的值必须与保存数据时使用的值完全相同;(2)第二个参数“无标记返回”的默认值是空字符,这里需要替换成空列表。在第一次进入应用时,收入记录中并没有数据,此时如果返回空字符,会给后续的程序编写带来麻烦。

以上是在App Inventor中对数据进行的常规操作,其实这些操作与数据库的关系并不大,相反,倒是与列表的操作密切相关。数据库组件的作用在于将操作结果保存到存储设备上。

还有一点需要提醒开发者,每次数据集合有所改动,都要及时将改动结果保存到数据库中,以免应用意外退出时(比如不小心碰到了设备上的返回键),数据丢失。

有了以上关于数据操作的基本知识,我们可以开始创建一个真实的应用了。这个帐本应用是笔者蓄谋已久的一个作品,早在互联网刚刚兴起时,就计划做一个可以随时记录收支信息的应用,尤其是希望记录下支出信息,但始终没有开始动手。时下智能手机的普及为随时随地的记录提供了无限的方便,加之有了App Inventor这样方便快捷的开发工具,帐本的开发势在必行了。

第三节 账本的功能模块设置

家庭账本的核心功能就是记帐、查账及统计,记账是为了查帐,查帐是为了知晓收入的来源与支出的去向,统计是为了总体评价某个时间段内的收支平衡情况。为了便于查询及统计,应用为收入及支出信息设置了若干种分类方式,用户可以对其中的部分分类方式进行添加、修改及删除操作,这就是设置功能的作用。此外,由于收支信息属于家庭内部的私有信息,为保护信息的安全,应用设置了登录功能,可以在设置功能中重置密码。应用的功能模块划分见图8- 15。其中的系统功能分别为应用的入口与出口,附属功能用于支持核心功能。

图8-15 家庭账本的功能模块

关于其中每各功能模块的细节,我们将在实现这一功能之前,给出具体说明。

第四节 登录页面的功能描述

一、预设选项功能

1、预设项

图8-16 将应用中的预设项保存在文本文件中

如图8- 16所示,我们将系统的预设项保存在文本文件GATEGORY.txt中,其中包含了六个预设项。注意图中的四个暗红色椭圆标记,它们将文件划分为五个部分,按照自上而下的顺序,它们分别为:

  • 支出分类——每一行代表一个分类:
    • 半角冒号“:”之前为一级分类,共12个一级分类,可用于查询及统计;
    • 半角冒号“:”之后为该一级分类下属的二级分类,可设置;
  • 收入类别——可用于查询及汇总,可设置;
  • 家庭成员——在收入记录中,是收入者的备选项;在支出记录中,是受益者的备选项;可用于查询及汇总,可设置;
  • 支出专项——支出的另一种分类方式(可设置),可用于标记某个特殊事项的支出,可用于查询及汇总,包含两项信息:
    • 专项名称:将显示在支出记录页面的下拉菜单中;
    • 激活:取值为“是”或“否”,只有取值为“是”的专项名称,才会出现在支出记录页面的下拉菜单中;
  • 支付方式——用于记录收入的支付手段,可设置。

2、加载预设项

在应用开发时,文件GATEGORY.txt被上传到项目中,保存在文件夹“/AppInventor/Assets/”下;在应用首次启动时,文件内容被加载到应用中,经过解析后,被保存到数据库中;当应用再次启动时,将在不同的功能页面,从数据库中读取不同的分类信息,并应用到具体的功能中。

如上一节所述,可以在系统设置功能中,对其中的五个预设项进行新增、修改及删除操作,也可以放弃已有的设置,恢复到默认设置(重新加载文件并保存到数据库中)。

二、密码保护功能

  • 当用户首次启动应用时,提示用户设置密码:
    • 用户需要输入密码及确认密码;
    • 如果密码与确认密码一致,则密码设置成功,自动转入功能导航页面;
    • 如果两次输入的密码不一致,提示用户重新输入;
  • 当用户再次启动应用时,提示用户输入密码:
    • 如果输入的密码正确,则转入功能导航页面;
    • 如果输入的密码错误,提示用户重新输入。

第五节 数据模型

一、对象模型

在信息管理类应用中,需要处理的数据较多,有些数据可以归为一组,如图8- 3中的收入记录,其中的7项数据,在整个应用中,它们始终作为一个整体而存在,共同来描述一个收入事项。应用中会保存很多条收入记录,但每条记录中都包含这7项信息,我们称单条的收入记录为一个对象(Object),它是我们要描述的客体(Object),而这7项数据是这个对象的7个属性(Attribute),它描述了一个对象的7个特质(Attribute),我们称这7项数据组成的结构为对象模型。理解这个概念可以帮助我们提高抽象思维的层次,当我们说“收入记录”时,我们可以忽略它的细节(7个属性),而把它简化成一个“名词”。

在我们的帐本应用中,两个重要的对象模型是“收入记录”与“支出记录”,此外,“支出专项”也构成一个对象模型,它包含专项名称及激活(状态)两个属性。

对象可以用下面的方式来表示:

{属性:属性值, 属性:属性值, …, 属性:属性值}

例如,收入记录对象可以表示为:

{日期:2015-3-5, 收入类别:工资, 发放者:SONY, 支付方式:转帐, 收入者:赵大同, 金额:8888, 备忘:2月}

支出专项对象可以表示为:

{专项名称:徒步运河, 激活:是}

对象表示法中属性的排列顺序不影响对象的“值”,例如 {专项名称:徒步运河, 激活:是} 与 {激活:是,专项名称:徒步运河} 是同一个对象。

二、变量模型

在帐本应用的每一个功能页面中(导航菜单页面除外),或者说在每一个屏幕中(MENU除外),都会有1个或多个全局变量,它们是整个页面操作的核心。如果把页面(屏幕)本身当作一个对象,那么全局变量就是页面(屏幕)的属性,而所有全局变量则组成了变量模型。

三、列表的文本表示

账本应用中大量使用列表操作,而App Inventor中的图形化编程语言,使得列表的表示方法占用了很大的版面,为了便于说明列表的结构,我们引入列表的文本表示方法。

  • 一级列表:(列表项1, 列表项2, …, 列表项n);
  • 二级列表:((列表项1, 列表项2, …, 列表项n), (列表项1, 列表项2, …, 列表项n), …, (列表项1, 列表项2, …, 列表项n))
  • 多级列表:(((a,(s,t,u),c),(e,f),(d,g)), ((x,y), (m,n,o), (q,p)))
  • 键值对列表:((键1, 值1), (键2, 值2), …, (键n, 值n))。 在列表的文本表示法中,用半角的“()”表示一个列表的边界,列表项之间以半角逗号“,”分隔,键值对列表只是普通列表的特例,即,二级列表中仅有两个列表项。

我们将“对象模型”、“变量模型”以及结构固定的数据列表统称为数据模型,在整个账本的开发过程中,我们会在正式开始编写程序之前,借用数据模型的概念,并借助于列表的文本表示方法,来描述程序中所要处理的数据内容。

四、登录页面的数据模型

1、预设项列表

我们用列表的文本表示法描述六个预设项的内容:

  • 支出一级分类:(吃喝, 穿戴, 住房, 家用, 日用, 交通, 通信,教育, 娱乐, 医疗, 社交, 金融, 杂项)
  • 支出二级分类:((粮油,肉蛋,蔬菜,水果,烟,酒,茶,水,零食,其他), (冬,夏,春秋,饰品), (房租,物业费,取暖费,水费,电费,煤气费,维修费), (电器,家具,床上用品,电脑,手机), (洗涤,护肤,保健), (公交,长途,出租,加油,停车,过路费,检修), (书籍,光盘,培训,家教,补习,留学), (电影,戏剧,K歌,旅游,运动,游戏,玩具,收藏), (体检,治疗,药物,手术,住院,处置,看护), (请客,往来,捐赠,公益), (房贷,车贷,其他), (家政服务))
  • 收入类别:(工资,奖金,补贴,劳务,理财,往来,受赠,其他)
  • 家庭成员:(张老三,李斯,王小五)
  • 支出专项 :(((专项名称,西藏自驾),(激活,是)), ((专项名称, 徒步运河),(激活,是)), ((专项名称, 自酿酒品),(激活,是)), ((专项名称, 攻读博士),(激活,是)))
  • 支付方式:(现金,转帐,其他)

2、变量模型

密码:这是登录页面中唯一的全局变量,用于保存从数据库中读取的密码值,首次启动应用时,数据库返回的值为空字符。

数据模型是我们进行界面设计以及程序编写的依据,下一节我们将据此创建登录页面——Screen1。

第六节 界面设计

首先创建一个新项目,项目名称为“简易家庭账本”,系统将自动创建第一个屏幕。该屏幕名称为Screen1,是系统的默认设置,不可更改。

1、设置Screen1的属性

Screen1是应用启动后用户看到的第一个界面,需要设置的属性较多,因此这里单独予以设置,相关属性设置如下:

  1. 应用说明:随时随地记录家庭的收支事项,查询收支的详细信息,按年度、月度及类别对收支状况进行统计汇总。\n对于金钱,不贪恋,不固着,不浪费;对于赚钱,该来的一定会来;对于花钱,该去的就让它去。(注:这项设置不是必需的,可以省去,也可以换成其他你喜欢的内容。)
  2. 水平、垂直对齐:居中;
  3. 应用名称:家庭账本——减少两个字,以便应用安装之后可以显示完整的应用名;
  4. 图标:上传一个小图片 ,将其设置为应用的图标,以便于在应用安装之后,用户在在众多的应用图标中进行查找;
  5. 显示标题栏:取消勾选。

上述的“应用说明”一项,当应用运行时,点击设备菜单按键,将弹出菜单选项,点击其中的“程序说明”,将弹出一个对话框,显示应用说明的内容,如图8- 17所示(最后一行是自动添加的)。注意其中有一个“\n”用于实现换行功能。

图8-17 应用说明的设置效果

2、添加组件

依据数据模型中的叙述,我们需要为文件加载、密码设置及登录功能提供必要的组件,包括可视组件(密码输入框、标签、按钮等)及非可视组件(文件管理器、本地数据库),如图8- 18所示。

图8-18 项目的设计视图

在Screen1中放置一个垂直布局组件,设置其宽高分别为85%,由于Screen1的水平及垂直对齐属性均为居中,因此垂直布局1位于屏幕的正中。

3、设置组件属性

组件的属性设置见表8- 1。

表8- 1登录页面的组件设置

4、上传资源

为项目上传两个资源文件,如图8- 17所示,在右下方的“素材”清单中,已经上传了两个文件,一个是MONEY.png,用于设置屏幕的图标属性;另一个是CATEGROY.txt,是系统预设项的数据文件。

第七节 页面逻辑

屏幕初始化时,系统将从本地数据库中读取密码信息,如果密码为空,则视同用户第一次打开应用,此时需要实现两项功能:加载保存预设项及设置密码;如果密码不为空,将密码保存到全局变量“密码”中,并实现登录功能。

1、加载保存预设选

在屏幕初始化时,如果读取的密码为空,则读取预设项数据文件CATEGORY.txt(文件存放位置为:/AppInventor/Assets/),与此相关的是文件管理器的收到文本事件。在该事件中,我们将文本解析为列表,并保存到数据库中。

2、密码设置

  • 界面组件的属性设置如表8- 1所示;
  • 用户输入密码并确认密码,然后点击开始按钮;
  • 如果输入的密码不为空,且与确认密码相同,则转到导航菜单页面,否则,用标签提示用户重新输入。
  • 一旦用户正确地设置密码,将密码保存在本地数据库中。

3、登录功能

  • 密码提示标签将显示“请输入密码”,同时隐藏水平布局2(包含密码确认框);
  • 用户输入密码,并点击开始按钮;
  • 将用户输入的密码与全局变量“密码”进行比较,如果两者相同,则转到导航菜单页面,否则提示用户重新输入。

在Screen1页面的生命周期中涉及三个事件:屏幕初始化事件、文件管理器的收到文本事件以及开始按钮点击事件,下面将针对这三个事件完成具体程序的编写。

第八节 编写程序

1、屏幕初始化

首先声明全局变量——密码,当屏幕初始化时,从本地数据库中获取标记为“密码”的值,如果密码不为空,说明用户已经成功设置了密码,则提示用户输入密码,并隐藏与确认密码相关的组件;如果密码为空,则读取预设项数据文件。代码如图8- 19所示。

图8-19 Screen1的屏幕初始化程序

2、文件管理器收到文本

在六个预设项中,支出一级分类与支出二级分类的数据混杂在一起,我们需要将其解析出来,为此,先创建一个有返回值的过程——解析支出分类,该过程的参数为“分类字串”,也就是数据文件中的第一部分内容,如图8- 16所示;该过程的返回值为列表,列表的第一项为一级分类,第二项为二级分类。代码如图8- 20所示。

图8-20 将支出分类的字串解析为列表

此外,我们还要为支出专项的数据添加“激活”项,为此创建一个有返回值的过程——支出专项列表,该过程的参数为“逗号分隔字串”,即数据文件中的第四部分;该过程的返回值为键值对列表,每个列表相中包含两个键值对,它们的键分别是“专项名称”与“激活”,代码如图8- 21所示。

图8-21 为支出专项添加“激活”数据

然后,我们在文件管理器的收到文本事件中,解析文件内容,并将所有预设项保存到数据库中。代码如图8- 22所示。

图8-22 文件管理器收到文本事件处理程序

这里需要特别留心支出二级分类的数据格式,它以逗号分隔字串的形式保存到数据库中。在后续开发中,我们在为二级分类的下拉框组件设置数据源时,要设置其“逗号分隔字串”属性,而非列表属性。

3、开始按钮点击程序

首先根据全局变量“密码”的值,分别对用户输入的信息进行判断,并给出对应的提示;当用户输入了正确的密码后,打开导航菜单屏幕,代码如图8- 23所示。

图8-23 开始按钮点击事件处理程序

上述代码还无法进行测试,我们还要添加一个屏幕——MENU,如图8- 24所示。这里需要提醒开发者,屏幕一旦添加完成,屏幕名称将无法更改,因此,在为屏幕添加组件之前,请确认屏幕的名称是有意义的,不要使用Screen2、Screen3这样的名称,因为在后续编程中,当屏幕越来越多时,程序的可读性会越来越差。如果觉得屏幕名称不妥,可以将新增的屏幕删除,再重新添加屏幕。另外,屏幕的名称只能包含字母、数字及下划线,并且必须以字母开头。这里我们为导航菜单屏幕取名为MENU,并且使用大写字母,以彰显屏幕组件在所有组件中的至高无上的地位。

图8-24 添加一个屏幕——MENU

第九节 测试

以上我们完成了登录页面的设计及编程,并创建了一个新屏幕——导航菜单屏幕,现在来测试一下上述程序,测试结果如图8- 25所示。

图8-25 Screen1测试结果

在多屏幕应用的测试过程中,涉及跳转屏幕的操作时,AI伴侣的反应速度显得有些慢,有时甚至没有反应,不过本次测试还算顺利。下一章我们将对导航菜单屏幕MENU进行设计并编程,并实现收入记录功能。