第 2 章 油漆桶

2023-02-16 13:41 更新

本章介紹Canvas組件,用它來(lái)生成簡(jiǎn)單的二維(2D)圖形,目標(biāo)是創(chuàng)建一個(gè)PaintPot(油漆桶)應(yīng)用,讓用戶在手機(jī)屏幕上繪制圖畫,并讓用戶用手機(jī)給自己拍照,然后在自己的照片上繪圖。回顧歷史,早在20世紀(jì)70年代,PaintPot是最早運(yùn)行在個(gè)人電腦上的應(yīng)用之一,目的是為了證明個(gè)人電腦的潛力。那時(shí)候,開發(fā)這樣一款簡(jiǎn)單的繪圖應(yīng)用是一項(xiàng)極其復(fù)雜的工作,而且繪圖效果也略顯粗糙。但現(xiàn)在,使用App Inventor,任何人都可以快速地創(chuàng)建一個(gè)有趣的繪圖應(yīng)用,這也是創(chuàng)建2D游戲的起點(diǎn)。

如圖2-1,油漆桶應(yīng)用將實(shí)現(xiàn)下列目標(biāo):

  • 用手指點(diǎn)取顏色并繪圖;

  • 用手指在手機(jī)屏幕上畫線;

  • 用手指觸碰手機(jī)屏幕畫圓點(diǎn);

  • 點(diǎn)擊按鈕來(lái)擦凈屏幕;

  • 點(diǎn)擊按鈕來(lái)改變繪制圓點(diǎn)的大?。?/p>

  • 用相機(jī)拍攝照片,并在照片上畫圖。

{%}

{%}

圖 2-1 油漆桶應(yīng)用

學(xué)習(xí)內(nèi)容

本章涵蓋了以下內(nèi)容:

  • 使用Canvas組件來(lái)繪制圖畫;

  • 處理屏幕上的觸摸及拖拽事件;

  • 使用arrangement組件來(lái)控制屏幕的外觀;

  • 使用帶有參數(shù)的事件處理程序;

  • 定義變量,來(lái)保存某些狀態(tài),如用戶繪制的圓點(diǎn)的大小。

準(zhǔn)備開始

首先檢查測(cè)試用的Android設(shè)備是否已經(jīng)為使用App Inventor做好了準(zhǔn)備:

  • Android設(shè)備中已經(jīng)安裝了“AI伴侶”;

  • 手機(jī)的WiFi連接已經(jīng)打開;

再訪問(wèn)App Inventor網(wǎng)站。新建項(xiàng)目“PaintPot”,點(diǎn)擊“Connect->AICompanion”,并按照提示操作,連接測(cè)試設(shè)備。

在正式開始之前,在組件設(shè)計(jì)器右側(cè)的“屬性”面板中,將“Screen1”的“Title”屬性修改為“油漆桶”。在測(cè)試設(shè)備上可以立即看到這一改變:應(yīng)用的標(biāo)題欄將顯示“油漆桶”。

這樣做是否會(huì)混淆了項(xiàng)目名稱與屏幕標(biāo)題呢(在英文版書中,將Title改為“PaintPot”,與項(xiàng)目同名,因此才有此疑問(wèn),對(duì)中文讀者來(lái)說(shuō)不存在這個(gè)疑問(wèn)?!g者注)?別擔(dān)心!在App Inventor中有三個(gè)非常重要名稱:

  • 項(xiàng)目名稱:同時(shí)也是應(yīng)用發(fā)布時(shí)所使用的名稱。提示:想修改項(xiàng)目名稱,可以點(diǎn)擊Project->Save project as,可以將原有項(xiàng)目賦予新的名稱,同時(shí)原有項(xiàng)目依然得以保留;

  • 組件名稱:一般的組件名稱都可以修改,但Screen1例外,在當(dāng)前版本中不能修改它的名稱;

  • 屏幕標(biāo)題:出現(xiàn)在設(shè)備的標(biāo)題欄中,是Screen組件的Title屬性,默認(rèn)值是Screen1,如第一章HelloPurr中所見,可以隨意修改它,如我們剛才將其改為“油漆桶”。

設(shè)計(jì)組件

創(chuàng)建“油漆桶”應(yīng)用需要以下組件:

  • 三個(gè)Button組件:用來(lái)選擇畫筆顏色:紅、藍(lán)或綠,放在HorizontalArrangement組件中;

  • 一個(gè)Button組件用來(lái)充當(dāng)橡皮;

  • 另外兩個(gè)Button組件用來(lái)改變畫筆的大?。?/p>

  • 一個(gè)Canvas組件,充當(dāng)畫布。Canvas具有BackgroundImage屬性,我們將其設(shè)置為第一章HelloPurr中的kitty.png,稍后還可以將背景圖片設(shè)置為用戶拍攝的照片。

創(chuàng)建顏色按鈕

首先按照以下提示創(chuàng)建三個(gè)顏色按鈕:

1. 拖一個(gè)Button組件到預(yù)覽窗口,設(shè)置其Text屬性為“紅”,BackgroundColor屬性設(shè)為紅色;

2. 在組件列表中選中Button1(可能已經(jīng)被選中),點(diǎn)擊Rename按鈕將組件名稱改為RedButton。注意組件名稱中不允許有空格,因此通常將組件名稱中每個(gè)單詞的首字母大寫。

3. 同樣,創(chuàng)建另外兩個(gè)按鈕,分別命名為BlueButton和GreenButton,將它們垂直地放在RedButton下方。對(duì)照?qǐng)D2-2,檢查一下你的操作結(jié)果。

{%}

圖 2-2 創(chuàng)建了3個(gè)按鈕的預(yù)覽窗口

注意:在項(xiàng)目中,建議為組建起一個(gè)有意義的名稱,而不是像第一章那樣采用默認(rèn)名稱。有意義的名稱增加了程序的可讀性,尤其是在切換到塊編輯器時(shí),將有助于區(qū)分不同的組件。本書中,采用慣用的駱駝命名法(如RedButton),即多單詞無(wú)空格的首字母大寫命名方式。

 測(cè)試:如果你還沒(méi)有點(diǎn)擊“Connect”來(lái)連接測(cè)試設(shè)備,那么做好連接,然后檢查一下應(yīng)用在設(shè)備(如果已經(jīng)連接)上的表現(xiàn)。

使用Arrangement組件改善布局

現(xiàn)在三個(gè)按鈕排成一列縱隊(duì),我們希望它們能排成一行,如圖2-3所示,使用HorizontalArrangement組件來(lái)實(shí)現(xiàn)組件的水平排列:

1. 在組件面板的Layout類中拖出HorizontalArrangement組件,放在按鈕下方;

2. 在屬性面板中,設(shè)置HorizontalArrangement的width屬性為“Fill Parent”(充滿父容器),以便在水平方向上占滿整個(gè)屏幕;

3. 將三個(gè)按鈕移動(dòng)到HorizontalArrangement中。注意,當(dāng)你拖拽按鈕時(shí),會(huì)看到一條藍(lán)色豎線,提示按鈕將會(huì)被放置在什么地方。

{%}

圖 2-3 在水平布局組件內(nèi)的三個(gè)按鈕

此時(shí)查看組件列表,你會(huì)發(fā)現(xiàn)三個(gè)按鈕縮進(jìn)排列在HorizontalArrangement項(xiàng)下,以顯示它們現(xiàn)在是次一級(jí)的組件。同時(shí)注意到所有組件都縮進(jìn)排在Screen1項(xiàng)下。

 測(cè)試:在測(cè)試設(shè)備的屏幕上,你會(huì)看到三個(gè)按鈕排列成一行,盡管看起來(lái)與預(yù)覽窗口中略有不同。如,在預(yù)覽窗口中可見的HorizontalArrangement周圍的輪廓線,在測(cè)試設(shè)備上則不可見。

通常采用布局組件來(lái)創(chuàng)建簡(jiǎn)單的垂直、水平或表格布局,也可以通過(guò)逐級(jí)插入(或嵌套)布局組件來(lái)創(chuàng)建更加復(fù)雜的布局。

添加Canvas(畫布)

Canvas像一塊畫布,用戶可以在上面繪畫(畫圓、畫等)。添加一個(gè)Canvas,并用第一章中的kitty.png作它的背景圖片(設(shè)置BackgroundImage屬性),具體步驟如下:

1. 打開組件面板中的Drawing and Amination(繪畫與動(dòng)畫)類,將Canvas組件拖到預(yù)覽窗口中,改名為DrawingCanvas,Width設(shè)為“Fill parent”,Height設(shè)為300pixels;

2. 如果你已經(jīng)完成了第一章的課程,那么文件kitty.png已經(jīng)下載;如果沒(méi)有,請(qǐng)?jiān)谶@里下載kitty.png。

3. 將DrawingCanvas的BackgroundImage設(shè)置為kitty.png:在設(shè)計(jì)器的屬性面板中,BackgroundImage的默認(rèn)值為None,點(diǎn)擊None及Upload File來(lái)添加kitty.png文件;

4. 將DrawingCanvas的PaintColor屬性設(shè)置為red,以便當(dāng)用戶剛啟動(dòng)應(yīng)用但尚未點(diǎn)擊顏色按鈕時(shí),畫筆為紅色。對(duì)照?qǐng)D2-4檢查一下你的操作。


圖 2-7 用戶觸摸畫布時(shí),應(yīng)用繪制一個(gè)圓點(diǎn)

在DrawingCanvas.DrawCircle塊的右側(cè)有三個(gè)插槽,需要填入三個(gè)參數(shù):x、y、r。其中x、y用于指定繪制圓形的位置,r用于指定圓的半徑。在屏幕左下角帶感嘆號(hào)的黃色警告顯示數(shù)字“1”,表示需要填滿這些插槽。從圖中看到,有兩組xy,這里要區(qū)分清楚:DrawingCanvas.Touched事件中的xy表示接觸點(diǎn)位置(已知);而DrawingCanvas.DrawCircle命令塊的xy插槽,用于設(shè)定繪制圓形的位置(待定)。我們恰好要在用戶的接觸點(diǎn)繪制圓形,因此DrawingCanvas.Touched事件中的xy值,可以作為DrawingCanvas.DrawCircle的x、y參數(shù),插入到插槽中。

 提示:可以從“when”塊中提取事件的參數(shù)值,將鼠標(biāo)懸停在參數(shù)上,將呼出“get”及“set”塊。可以將“get x”塊拖出并插到x插槽中,作為DrawCircle命令的x值。如圖2-8所示。


圖 2-12 添加畫線功能

DrawingCanvas.DrawLine塊有四個(gè)參數(shù),兩點(diǎn)確定一線:設(shè)(X1,Y1)為起點(diǎn),(X2,Y2)為終點(diǎn)。你能確定每個(gè)參數(shù)中需要插入什么值嗎?記住,當(dāng)手指在DrawingCanvas上拖動(dòng)時(shí),拖動(dòng)事件將被調(diào)用很多次:在應(yīng)用中,手指的每次移動(dòng)都會(huì)繪制出一個(gè)微小線段,從(Prevx, prevy)到(currentX, currentY)?,F(xiàn)在把它們填入DrawingCanvas.DrawLine塊。

3. 拖出“get”塊來(lái)充當(dāng)畫線的參數(shù)。將get prevX與get prevY分別插入到x1和y1插槽;而get currentX與get currentY插入到x2和y2插槽,如圖2-13所示。

{%}

圖 2-13 用戶在屏幕上拖動(dòng)手指,應(yīng)用就在前一位置與當(dāng)前位置之間畫一條微小線段

 測(cè)試:在設(shè)備上測(cè)試一下剛剛設(shè)定的行為:在屏幕上隨意拖動(dòng)手指,畫出線段及曲線;觸碰屏幕畫出一個(gè)圓點(diǎn)。

添加按鈕事件處理程序

應(yīng)用已經(jīng)實(shí)現(xiàn)了畫線功能,但現(xiàn)在只能畫紅線。下面添加顏色按鈕的事件處理程序,用戶可以改變畫筆的顏色;同樣設(shè)置清除按鈕WipeButton,以便用戶可以清除畫面并重新開始。

在塊編輯器中:

1. 展開左側(cè)塊的(Blocks)列表;

2. 打開RedButton抽屜,拖出RedButton.Click塊;

3. 打開DrawingCanvas抽屜。拖出set DrawingCanvas.PaintColor塊(可能需要滾動(dòng)塊的列表以便在抽屜里找到它),并把它放在RedButton.Click塊“do”的位置;

4. 打開Colors抽屜,拖出紅色塊,將其插入set DrawingCanvas.PaintColor塊的插槽;

5. 重復(fù)步驟2-4,設(shè)置藍(lán)色和綠色按鈕;

6. 最后設(shè)置WipeButton按鈕。從WipeButton抽屜中拖出WipeButton.Click塊。再?gòu)腄rawingCanvas抽屜里拖出DrawingCanvas.Clear塊,并將其放在WipeButton.Click塊中。確認(rèn)所有塊顯示如圖2-14所示。

{%}

圖 2-14 單擊顏色按鈕改變DrawingCanvas的畫筆顏色;單擊清除按鈕清空屏幕

讓用戶拍照片

App Inventor應(yīng)用可以與Android設(shè)備的強(qiáng)大功能進(jìn)行交互,包括相機(jī)功能。為了增加應(yīng)用的趣味性,用戶可以將繪圖背景設(shè)置為他們用相機(jī)拍攝的照片。

1. Camera組件有兩個(gè)關(guān)鍵的塊:Camera.TakePicture塊用來(lái)啟動(dòng)設(shè)備上的拍照程序;拍照完成將觸發(fā)Camera.AfterPicture事件。在Camera.AfterPicture事件處理程序中,可以將剛剛拍攝的照片設(shè)置為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事件有一個(gè)名為image的參數(shù),代表剛剛拍攝的照片,將從Camera1.AfterPicture塊中得到的get image塊插入DrawingCanvas.BackgroundImage塊。

所有的塊如圖2-15所示 。

{%}

圖 2-15 拍完的照片被設(shè)置為DrawingCanvas的背景圖片

 測(cè)試:在設(shè)備上點(diǎn)擊“拍照”按鈕并拍攝照片,貓的圖片變成了你拍的照片。你可以在自己的照片上進(jìn)行繪畫。(用Wolber教授的照片繪畫是學(xué)生們的一大樂(lè)事,如圖2-16。)(Wolber教授是本書的作者之一。)

改變畫筆大小

{%}

圖 2-16 帶有Wolber教授涂鴉照片的PaintPot應(yīng)用

在DrawingCanvas上畫圓點(diǎn),其大小由DrawingCanvas.DrawCircle塊中參數(shù)r決定。改變r(jià)值可以改變圓點(diǎn)的大小。試試看將5改為10,然后在測(cè)試設(shè)備上查看結(jié)果。

另一個(gè)問(wèn)題是,無(wú)論開發(fā)者如何設(shè)置參數(shù)r,用戶都只能用這個(gè)固定的尺寸。如何讓用戶來(lái)改變圓點(diǎn)的大小呢?為此我們來(lái)修改程序:當(dāng)用戶點(diǎn)擊“大圓”按鈕時(shí),圓點(diǎn)半徑設(shè)為8,當(dāng)點(diǎn)擊“小圓”時(shí)半徑設(shè)為2。

我們要用不同的半徑畫圓,但應(yīng)用怎么知道我們要用哪個(gè)值呢?必須通知應(yīng)用我們選定的值,而應(yīng)用必須以某種方式記?。ɑ虮4妫┻@個(gè)值,這樣才能在需要的時(shí)候使用它。之前我們所使用的值,要么設(shè)定為屬性(如畫筆顏色),要么用固定的數(shù)字塊(如畫筆大?。F(xiàn)在應(yīng)用需要記住一些屬性之外的、不是固定不變的東西,這就需要定義一個(gè)變量。變量是一個(gè)存儲(chǔ)單元,可以把它想象成一個(gè)容器,里面存儲(chǔ)著可變的數(shù)據(jù),如畫筆的大?。ㄓ嘘P(guān)變量的詳細(xì)信息,請(qǐng)參見App Inventor指南第16章)。

讓我們先來(lái)定義一個(gè)變量dotSize:

1. 在塊編輯器中,從Variables(變量)抽屜中拖出一個(gè)initialize global name to塊。將“name”改為“dotSize”;

2. 請(qǐng)注意,initialize global dotSize to塊有一個(gè)開放的插槽,可以在這里設(shè)定變量的初始值,或者說(shuō)是應(yīng)用啟動(dòng)時(shí)的默認(rèn)值(編程術(shù)語(yǔ)稱為“初始化變量”)。在本應(yīng)用中,用數(shù)字塊2來(lái)初始化變量dotSize,(創(chuàng)建塊“2”的方法有兩種:在空白區(qū)直接輸入“2”然后回車;或從Math抽屜中拖出“0”塊,將0改為2。)將其插到initialize global dotSize to塊的插槽中,如圖2-17所示。

{%}

圖 2-17 將dotSize變量的初始值設(shè)為2

使用變量

下一步,我們要修改DrawingCanvas.Touched事件處理程序,將其中DrawingCanvas.DrawCircle塊的參數(shù)r的固定值用變量dotSize來(lái)代替。(我們先將dotSize的初始值設(shè)定為“固定”的2,但稍后我們將改變dotSize的值,并同時(shí)改變畫筆的大小。)

1. 從initialize global dotSize to塊中拖出一個(gè)get global dotSize塊,用它來(lái)提供變量的值;

2. 轉(zhuǎn)到DrawingCanvas.Touched事件處理程序,將數(shù)字塊“5”拖出插槽并扔進(jìn)垃圾桶,用get global dotSize塊來(lái)替換(見圖2-18)。當(dāng)用戶觸摸到DrawingCanvas時(shí),應(yīng)用將根據(jù)dotSize的大小來(lái)確定圓點(diǎn)的半徑。

{%}

圖 2-18 畫筆的大小取決于變量dotSize中保存的值

修改變量值

現(xiàn)在變量魔法登場(chǎng),變量dotSize允許用戶選擇畫筆的大小,而事件處理程序也將以dotSize為半徑來(lái)畫圓。通過(guò)設(shè)計(jì)SmallButton.Click和BigButton.Click的事件處理程序來(lái)實(shí)現(xiàn)此功能:

1. 從SmallButton抽屜中拖出SmallButton.Click事件處理程序;再?gòu)腣ariables抽屜中拖出一個(gè)“set”塊,下拉選擇global dotSize,并將其插入SmallButton.Click塊;最后,創(chuàng)建一個(gè)數(shù)字塊“2”,并將其插入set global dotSize塊。

2. 創(chuàng)建另一個(gè)類似的BigButton.Click事件處理程序,設(shè)置畫筆大小為8。這兩個(gè)事件處理程序顯示在塊編輯器中,如圖2-19所示。

{%}

圖 2-19 點(diǎn)擊SmallButton及BigButton按鈕改變畫筆大小,之后將以該尺寸繪制圖形

 提示: get/set global dotSize 之中的“global”(全局)指的是該變量適用于程序中所有的事件處理程序(全局)。與global相對(duì)的是“l(fā)ocal”(局部)變量,適用于程序的特定部分;App Inventor 2中添加了此項(xiàng)功能,第12章首次使用。

{%} App inventor網(wǎng)站,可以嘗試譯者提供的替代版本,或點(diǎn)擊頁(yè)面右上角的“開發(fā)體驗(yàn)”按鈕。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)