💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 第 2 章 画笔画布 **教学制作**:一克拉 **App作品下载**: https://share.weiyun.com/c517583c14e54d9aaf1d956fdb2fda32 ![](https://box.kancloud.cn/cf979a2392e59d70a506ecdce060cf9c_245x286.jpg) **App应用的外观图**(结果展示) ![](https://box.kancloud.cn/d51f92d536cf17065e59ad70c504bf63_188x256.png) 一、【学习目标】 创建一个PaintPot(油漆桶)应用,让用户在手机屏幕上绘制图画,并让用户用手机给自己拍照,然后在自己的照片上绘图。 使用App Inventor,任何人都可以快速地创建一个有趣的绘图应用,这也是创建2D游戏的起点。 油漆桶应用将实现下列目标: • 用手指点取颜色并绘图; • 用手指在手机屏幕上画线;> • 用手指触碰手机屏幕画圆点; • 点击按钮来擦净屏幕; • 点击按钮来改变绘制圆点的大小; • 用相机拍摄照片,并在照片上画图。 二、【学习内容】 1 使用Canvas组件来绘制图画; 2 处理屏幕上的触摸及拖拽事件; 3 使用arrangement组件来控制屏幕的外观; 4 使用带有参数的事件处理程序; 5 定义变量,来保存某些状态,如用户绘制的圆点的大小。 三、【制作组件】7个按钮,2个布局,1照相,1画布 1、颜色按钮三个 红蓝绿 Button(头标)加 水平布局组件一个 HorizontalArrangement 2、画布组件Canvas 放图像 3、四个功能按钮(底标)加水平布局一个 4、照相机(非可视组件) 四、【制作程序】 1、全局变量:画笔大小 。设初值2 。 一块程序。 2、触碰画布时画圆点,用到变量,设置x、y、r 。 一块程序。 3、拖拽时画线 前点、当前点 。一块程序。 4、功能按钮四个,红、蓝、绿、清除。 6、照相机二块程序:调出拍,之后设置用图。 7、改画笔大小二个按钮,二块程序。 五、【制作步骤】 1、注意: 项目名称:同时也是应用发布时所使用的名称。提示:想修改项目名称,可以点击Project->Save project as,可以将原有项目赋予新的名称,同时原有项目依然得以保留; 组件名称:一般的组件名称都可以修改,但Screen1例外,在当前版本中不能修改它的名称; 屏幕标题:出现在设备的标题栏中,是Screen组件的Title属性,默认值是Screen1,可以随意修改它,将其改为“油漆桶”。 2、创建三个颜色按钮(创建组件) ![](https://box.kancloud.cn/025260d145e4e06005b63f9e92131132_604x224.png) 注意: 在项目中,建议为组建起一个有意义的名称,而不是像第一章那样采用默认名称。有意义的名称增加了程序的可读性,尤其是在切换到块编辑器时,将有助于区分不同的组件。 采用惯用的骆驼命名法(如RedButton),即多单词无空格的首字母大写命名方式。 3、改善布局 方法:拖拽法 如图:拖拽按钮时,会看到一条蓝色竖线,提示按钮将会被放置在什么地方。 三个按钮缩进排列在HorizontalArrangement项下,以显示它们现在是次一级的组件。 ![](https://box.kancloud.cn/afe6e4a7aab8b7b8dbe7af230897d85c_596x161.png) HorizontalArrangement周围的轮廓线,在测试设备上则不可见。 通常采用布局组件来创建简单的垂直、水平或表格布局,也可以通过逐级插入(或嵌套)布局组件来创建更加复杂的布局。 4、添加Canvas(画布) Canvas像一块画布,用户可以在上面绘画(画圆、画等)。添加一个Canvas,并用第一章中的kitty.png作它的背景图片(设置BackgroundImage属性),具体步骤如下: (1). 打开组件面板中的Drawing and Amination(绘画与动画)类,将Canvas组件拖到预览窗口中,改名为DrawingCanvas,Width设为“Fill parent”,Height设为300pixels; (2). 如果你已经完成了第一章的课程,那么文件kitty.png已经下载;如果没有,请在这里下载kitty.png。 (3). 将DrawingCanvas的BackgroundImage设置为kitty.png:在设计器的属性面板中,BackgroundImage的默认值为None,点击None及Upload File来添加kitty.png文件; (4). 将DrawingCanvas的PaintColor属性设置为red,以便当用户刚启动应用但尚未点击颜色按钮时,画笔为红色。 ![](https://box.kancloud.cn/24a5760649af0db2137a3b3c57401266_763x569.png) 5、设置底部4个按钮及照相机组件 (1). 从组件面板中拖出第二个HorizontalArrangement,放在canvas下方,再拖两个Button并置于屏幕底部的HorizontalArrangement中;将第一个按钮改名为TakePictureButton,Text属性设为“拍照”;第二个按钮改名为WipeButton,Text属性设为“清除”; (2). 再拖两个Button组件到HorizontalArrangement中,放在“清除”按钮后面; (3). 两个Button分别命名为BigButton、SmallButton,Text属性分别设为“大圆”、“小圆”; (4). 从组件的Media类中拖出一个Camera组件放在预览窗口中,它将落在非可视组件区。 到此为止,应用外观已经设置完成。 6为组件添加行为(加块程序) 让组件关联起来完成动作任务。 处理用户的触摸及拖拽事件,也可以实现绘画及拍照功能。 Canvas组件具有Touched及Dragged事件, 针对DrawingCanvas.Touched(触碰)事件编程,调用DrawingCanvas.DrawCircle(画圆)程序; 针对DrawingCanvas.Dragged(拖拽)事件编程来调用DrawingCanvas.DrawLine(画线)程序。 针对按钮编程,设置DrawingCanvas.PaintColor(画笔颜色)属性 针对按钮 清除DrawingCanvas, 将DrawingCanvas的背景图片修改为照相机拍摄的图片。 (1)设置触碰行为 当用户触碰DrawingCanvas时,在接触点绘制一个圆点。 ![](https://box.kancloud.cn/5eb9e34765a3a2f71a6004b7739ee52d_267x88.png) 第一:拖出DrawingCanvas.Touched程序块 打开DrawingCanvas抽屉拖出DrawingCanvas.Touched块,该块有三个参数x、y及touchedSprite,如图2-6所示。这些参数提供了接触点的位置信息; 【提示】在第一章HelloPurr应用中已经熟悉了Button.Click事件,但对Canvas事件还很陌生。Button.Click事件的发生很简单,不附带任何其他信息;但有些事件则不然,它们附带了与事件有关的“参数”信息。 DrawingCanvas.Touched事件中的x、y代表接触点在DrawingCanvas中的坐标,而touchedSprite代表接触点所碰到的DrawingCanvas中的对象(在App Inventor中称作sprite—精灵),但在第三章之前我们不会用到它。我们将利用接触点的xy坐标来绘制圆点。 第二:拖出DrawingCanvas.DrawCircle程序块 从DrawingCanvas抽屉中拖出DrawingCanvas.DrawCircle命令块,放在DrawingCanvas.Touched事件处理程序中 【*设xy*】在DrawingCanvas.DrawCircle块的右侧有三个插槽,需要填入三个参数:x、y、r。 其中x、y用于指定绘制圆形的位置,r用于指定圆的半径。在屏幕左下角带感叹号的黄色警告显示数字“1”,表示需要填满这些插槽。 从图中看到,有两组xy,这里要区分清楚:DrawingCanvas.Touched事件中的xy表示接触点位置(已知); 而DrawingCanvas.DrawCircle命令块的xy插槽,用于设定绘制圆形的位置(待定)。我们恰好要在用户的接触点绘制圆形,因此DrawingCanvas.Touched事件中的xy值,可以作为DrawingCanvas.DrawCircle的x、y参数,插入到插槽中。 ![](https://box.kancloud.cn/8c3d8185ad5fc4a8e4f5aefa67447dac_348x168.png) 图 2-8 读取事件参数:从DrawingCanvas.Touched事件中拖出“get x”块 ![](https://box.kancloud.cn/f41037cd32172f306276b62e97057385_348x140.png) 【设半径r】长度的单位是pixel(像素),是屏幕上能够绘制的最小的点。 设r = 5:点击屏幕的空白区域,输入5然后回车(自动创建数字块“5”)并将其插入插槽r中。再看屏幕左下角的黄色三角形,数字由1变为0,因为所有插槽都被填满了 ![](https://box.kancloud.cn/31044e85ada79af088baf8d9127bc0c4_348x140.png) 提示:在块编辑器中输入5然后回车,这种操作叫做输入块(typeblocking)。 块编辑器会根据你输入的字符,显示与该字符相匹配的一系列块;如果输入的是数字,那么将创建一个数字块。 意思是:当用户触碰DrawingCanvas时,将在(x,y)点绘制一个半径为5的圆形。 触碰 DrawingCanvas(画布),手指碰过的地方会留下一个圆点。如果在设计器中将DrawingCanvas.PaintColor属性设置为红色,那么圆点也是红色(否则应该是默认的黑色)。 (2)设置拖拽行为 知识点: 触碰(Toughed)事件与拖拽(Dragged)事件的区别: • 触碰事件:手指在DrawingCanvas(画布)上放下再抬起,其间手指没有移动。 • 拖拽事件:手指在DrawingCanvas(画布)上放下,手指与屏幕保持接触并移动。 在绘图程序中,手指在屏幕上拖动,沿着手指移动的路径,将绘制出一条曲线,因为这条曲线由数微小的线段构成:手指每次微小的移动,都将绘制一个微小的线段。 第一:DrawingCanvas.Dragged程序块。起点终点参数 • StartX、StartY:手指开始拖动时所在的位置(整个曲线的起点); • currentX、currentY:手指的当前位置(微小线段的终点); • prevX、prevY:手指的上一个位置(微小线段的起点); • draggedSprite:布尔值,如果用户直接拖动一个图片,则其值为真。 ![](https://box.kancloud.cn/a254459d3d295b13d649b841f489574b_639x90.png) Dragged事件携带了更多参数 第二:DrawingCanvas.DrawLine程序块。添加画线功能 ![](https://box.kancloud.cn/e0717518231576d98797679cfe2ea19e_634x192.png) 有四个参数,两点确定一线:设(X1,Y1)为起点,(X2,Y2)为终点。 当手指在DrawingCanvas上拖动时,拖动事件将被调用很多次: 在应用中,手指的每次移动都会绘制出一个微小线段,每次从微小邻点(Prevx, prevy)到(currentX, currentY)。 第三:拖出“get”块来充当画线的参数。变量座标 将get prevX与get prevY分别插入到x1和y1插槽;而get currentX与get currentY插入到x2和y2插槽。 ![](https://box.kancloud.cn/24c19200878fd9c320f7bfa138b57d46_636x194.png) 第四:设置三个颜色按钮及清除按钮 程序块 在块编辑器中: (1). 展开左侧块的(Blocks)列表; (2). 打开RedButton抽屉,拖出RedButton.Click块; (3). 打开DrawingCanvas抽屉。拖出set DrawingCanvas.PaintColor块(可能需要滚动块的列表以便在抽屉里找到它),并把它放在RedButton.Click块“do”的位置; (4). 打开Colors抽屉,拖出红色块,将其插入set DrawingCanvas.PaintColor块的插槽; (5). 重复步骤2-4,设置蓝色和绿色按钮; (6). 最后设置WipeButton按钮。从WipeButton抽屉中拖出WipeButton.Click块。再从DrawingCanvas抽屉里拖出DrawingCanvas.Clear块,并将其放在WipeButton.Click块中。确认所有块显示如图2-14所示。 ![](https://box.kancloud.cn/b464e9dec6cee17b4f43f7db150d2870_670x241.png) 思路:按钮点击-执行do-set设置另一组件画布上的画笔- 思路:按钮点击-让call-画布清理。 两个组件关联上了。 单击颜色按钮改变DrawingCanvas的画笔颜色;单击清除按钮清空屏幕。 第五:让用户拍照片更换app画布。TakePictureButton按钮设置程序块 App Inventor应用可以与Android设备的强大功能进行交互,包括相机功能,用户可以将绘图背景设置为自己用相机拍摄的照片。 (1). Camera组件有两个关键的块: Camera.TakePicture块用来启动设备上的拍照程序;拍照完成将触发Camera.AfterPicture事件。在Camera.AfterPicture事件处理程序中,可以将刚刚拍摄的照片设置为DrawingCanvas.BackgroundImage。 打开TakePictureButton抽屉并拖出TakePictureButton.Click事件处理程序; (2). 从Camera1抽屉拖出Camera1.TakePicture放在TakePictureButton.Click事件处理程序中,就是开始照相。 (3). 从Camera1的抽屉中拖出Camera1.AfterPicture事件处理程序;后期处理 (4). 从DrawingCanvas抽屉拖出set DrawingCanvas.BackgroundImage块放在Camera1.AfterPicture事件处理程序中;让画布的背景图变为刚拍摄的图 (5). Camera1.AfterPicture事件有一个名为image的参数代表刚刚拍摄的照片,将从Camera1.AfterPicture块中得到的get image块插入DrawingCanvas.BackgroundImage块。 所有的块如图2-15所示 。 ![](https://box.kancloud.cn/ca4b8bcd00f355de70df09c7fd95f37e_560x117.png) 拍完的照片被设置为DrawingCanvas的背景图片 第六:改变画笔大小程序块BigButton和SmallButton 问题1:在DrawingCanvas上画圆点,其大小由DrawingCanvas.DrawCircle块中参数r决定。改变r值可以改变圆点的大小。试试看将5改为10,然后在测试设备上查看结果。 问题2:无论开发者如何设置参数r,用户都只能用这个固定的尺寸。如何让用户来改变圆点的大小呢?就需要定义一个变量。变量是一个存储单元,可以把它想象成一个容器,里面存储着可变的数据,如画笔的大小。 ❶定义变量dotSize: (1). 在块编辑器中,从Variables(变量)抽屉中拖出一个initialize global name to块。将“name”改为“dotSize”; (2). 请注意,initialize global dotSize to块有一个开放的插槽,可以在这里设定变量的初始值,或者说是应用启动时的默认值(编程术语称为“初始化变量”)。在本应用中,用数字块2来初始化变量dotSize,(创建块“2”的方法有两种:在空白区直接输入“2”然后回车;或从Math抽屉中拖出“0”块,将0改为2。)将其插到initialize global dotSize to块的插槽中,如图2-17所示。 ![](https://box.kancloud.cn/c97dd14a0c14a154abad1d6fa8af239c_288x29.png) 图 2-17 将dotSize变量的初始值设为2 ❷使用变量 我们要修改DrawingCanvas.Touched事件处理程序,将其中DrawingCanvas.DrawCircle块的参数r的固定值用变量dotSize来代替。(我们先将dotSize的初始值设定为“固定”的2,但稍后我们将改变dotSize的值,并同时改变画笔的大小。) (1). 从initialize global dotSize to块中拖出一个get global dotSize块,用它来提供变量的值; (2). 转到DrawingCanvas.Touched事件处理程序,将数字块“5”拖出插槽并扔进垃圾桶,用get global dotSize块来替换(见图2-18)。当用户触摸到DrawingCanvas时,应用将根据dotSize的大小来确定圆点的半径。 ![](https://box.kancloud.cn/a18ab0f7e7b640bb1fcaa7be5cf7652a_519x167.png) 图 2-18 画笔的大小取决于变量dotSize中保存的值 ❸修改变量值 现在变量魔法登场,变量dotSize允许用户选择画笔的大小,而事件处理程序也将以dotSize为半径来画圆。通过设计SmallButton.Click和BigButton.Click的事件处理程序来实现此功能: (1). 从SmallButton抽屉中拖出SmallButton.Click事件处理程序;再从Variables抽屉中拖出一个“set”块,下拉选择global dotSize,并将其插入SmallButton.Click块;最后,创建一个数字块“2”,并将其插入set global dotSize块。 (2). 创建另一个类似的BigButton.Click事件处理程序,设置画笔大小为8。这两个事件处理程序显示在块编辑器中,如图2-19所示。 ![](https://box.kancloud.cn/726e0bcb1c6282be870afd73f9f69b3c_580x69.png) 图 2-19 点击SmallButton及BigButton按钮改变画笔大小,之后将以该尺寸绘制图形  【提示】: get/set global dotSize 之中的“global”(全局)指的是该变量适用于程序中所有的事件处理程序(全局)。与global相对的是“local”(局部)变量,适用于程序的特定部分;App Inventor 2中添加了此项功能,第12章首次使用。  【测试】尝试单击“大圆”、“小圆”按钮,然后在DrawingCanvas上触碰,所绘圆点的大小是否不同?画线呢?圆有变化而线没有变化,因为只有DrawingCanvas.DrawCircle块的半径r使用了变量dotSize。在此基础上,考虑修改块的设置,以使画笔的大小line线条对画线也同样有效。注意:DrawingCanvas有一个“LineWidth(线宽)”的属性。要加线宽属性。 ### 总结:油漆桶的完整应用。 1、程序块 ![](https://box.kancloud.cn/667811ac21bfcb94e549c9f82059a054_729x635.png) 2、骆驼命名法 这是一个编程术语,指的是变量的命名规则:由于变量名中不允许出现空格,因此当需要用多个英文单词为变量命名时,通过每个单词的首字母大写来区分不同的单词,如本例中的红色按钮命名为RedButton,其中第一个单词的首字母也可以小写,即redButton。 3、改进 可以考虑做以下改进: 1. 用户界面中没有显示当前的状态信息(如画笔大小或颜色),只能通过画图来得知这些信息。修改应用,向用户显示当前的状态信息; 2. 让用户在TextBox组件内输入画笔的尺寸,这样一来,除了2和8之外,他还可以将其更改为其他数值。有关TextBox组件的详细信息,请参阅第4章。 4、本章涵盖了如下内容: (1) DrawingCanvas组件:用于在其中绘画,也可以感知触摸及拖动事件,可以利用这些事件来实现绘图功能; (2)使用布局组件(HorizontalAarrangement),使多个组件的布局条理化,而不是摞在一起; (3)有些事件处理程序附带了与事件有关的信息,例如Toughed事件中附带了触摸点的坐标,这些信息用参数来表示。在使用带参数的事件处理程序时,App Inventor以块的方式生成“get”及“set”项,来获取这些参数的引用; (4)创建变量可以使用Variables抽屉中的initialize global name to块,变量可以让应用记住那些没有被存储成组件属性的信息,如画笔的大小; (5)对于定义的每一个变量,App Inventor提供了变量的读写方法:get global variable用来获取变量的值(读),而set global variable用来设置/修改变量的值(写)。可以从变量初始化块的变量名中拖出“get”或“set”块。 THE END