第8章的“總統(tǒng)測(cè)驗(yàn)”可以被定制成各種測(cè)驗(yàn),但這種定制只對(duì)App Inventor程序員有用。只有程序員可以修改問題和答案,而對(duì)于父母、老師或其他用戶來說,他們無法創(chuàng)建一個(gè)測(cè)驗(yàn)或變換問題(除非他們也學(xué)App Inventor!)。
本章將構(gòu)建一個(gè)“出題”應(yīng)用,“老師”可以在輸入表單中創(chuàng)建試題。試題和答案將被存儲(chǔ)在Web數(shù)據(jù)庫中,以便“學(xué)生”可以單獨(dú)訪問“答題”應(yīng)用并參加考試。通過創(chuàng)建這兩個(gè)應(yīng)用,你會(huì)在概念上產(chǎn)生更大的飛躍,并學(xué)習(xí)如何創(chuàng)建一個(gè)應(yīng)用,讓用戶自行生成數(shù)據(jù),并實(shí)現(xiàn)用戶之間跨應(yīng)用的數(shù)據(jù)共享。
“出題”與“答題”這兩個(gè)應(yīng)用協(xié)同工作,讓“老師”可以為“學(xué)生”出題。父母可以在長(zhǎng)途旅行中做一些旅行花絮類的應(yīng)用,以增加孩子們的樂趣;小學(xué)教師可以創(chuàng)建“數(shù)學(xué)突擊”一類的小測(cè)驗(yàn);而大學(xué)生們可以創(chuàng)建一系列的測(cè)驗(yàn),幫助他們的學(xué)習(xí)小組來準(zhǔn)備期末考試。本章建立在第8章“總統(tǒng)測(cè)驗(yàn)”的基礎(chǔ)上,如果你還沒學(xué)過,在繼續(xù)本章之前,請(qǐng)先學(xué)習(xí)第8章。
本章將設(shè)計(jì)兩個(gè)應(yīng)用:針對(duì)“老師”的“出題”應(yīng)用(見圖10-1)以及針對(duì)“學(xué)生”的“答題”應(yīng)用。在“出題”應(yīng)用中:
用戶在輸入表單中輸入問題及答案;
顯示輸入的一對(duì)問答;
圖 10-1 出題應(yīng)用
“答題”應(yīng)用的功能與之前的“總統(tǒng)測(cè)驗(yàn)”類似。事實(shí)上,是以“總統(tǒng)測(cè)驗(yàn)”為起點(diǎn)創(chuàng)建“答題”應(yīng)用,不同的是,這里的問題是使用“出題”應(yīng)用輸入并保存在數(shù)據(jù)庫中的。
“總統(tǒng)測(cè)驗(yàn)”是一個(gè)使用靜態(tài)數(shù)據(jù)的應(yīng)用范例:不管用戶做多少次測(cè)驗(yàn),問題都是一樣的,因?yàn)閱栴}被寫在程序中(稱為“硬編碼”)。新聞應(yīng)用、博客以及像Facebook和Twitter這類的社交網(wǎng)絡(luò)應(yīng)用采用的是動(dòng)態(tài)數(shù)據(jù),這意味著數(shù)據(jù)隨時(shí)在改變。通常這種動(dòng)態(tài)信息由用戶生成,這類應(yīng)用允許用戶輸入、修改并共享信息。在“出題”與“答題”應(yīng)用中,將學(xué)習(xí)創(chuàng)建一個(gè)應(yīng)用,來處理用戶生成的數(shù)據(jù)。
在第9章“木琴”應(yīng)用中,我們首次引入動(dòng)態(tài)列表概念:用戶輸入的音符被記錄在列表中。由用戶生成數(shù)據(jù)的應(yīng)用更為復(fù)雜,而且使用的塊也更抽象,因?yàn)闆]有預(yù)設(shè)的靜態(tài)數(shù)據(jù)可供參照。盡管可以定義列表變量,但不能設(shè)置具體的項(xiàng)。在編寫程序的同時(shí),需要設(shè)想最終用戶輸入的數(shù)據(jù)被添加到列表中。
本章涵蓋了App Inventor中的如下內(nèi)容:
輸入表單:允許用戶輸入信息;
顯示來自多個(gè)列表的數(shù)據(jù)項(xiàng);
永久保存數(shù)據(jù):“出題”應(yīng)用將問題和答案保存到網(wǎng)絡(luò)數(shù)據(jù)庫中,“答題”應(yīng)用將從同一個(gè)數(shù)據(jù)庫中加載它們;
登陸App Inventor網(wǎng)站,創(chuàng)建新項(xiàng)目“MakeQuiz”,屏幕標(biāo)題設(shè)為“出題”,并連接到測(cè)試手機(jī)或模擬器。
使用組件設(shè)計(jì)器來創(chuàng)建用戶界面,如圖10-2所示(圖的后面有更詳細(xì)的說明),組件清單列于表10-1中。從Palette中拖出組件,將名稱改為表中的命名。注意,標(biāo)題Label的名稱(Label1 – Label3)不必改,就用它們的默認(rèn)值(因?yàn)樵诰庉嬈髦胁粫?huì)使用這些名稱)。
表10-1 “出題”應(yīng)用中的所有組件
組件類型 | 面板中分組 | 命名 | 作用 |
---|---|---|---|
TableArrangement | Layout | TableArrangement1 | 格式化表單,包括問題及答案 |
Label | User Interface | Label1 | 提示“問題:” |
TextBox | User Interface | QuestionText | 用戶在此輸入問題 |
Label | User Interface | Label2 | 提示“答案:” |
TextBox | User Interface | AnswerText | 用戶在此輸入答案 |
Button | User Interface | SubmitButton | 用戶點(diǎn)擊提交問題-答案對(duì)兒 |
Label | User Interface | Label3 | 顯示“測(cè)驗(yàn)的問題及答案?!?/td> |
Label | User Interface | QuestionAnswersLabel | 顯示之前輸入的成對(duì)的問題答案 |
TinyWebDB | Storage | TinyWebDB1 | 用數(shù)據(jù)庫保存并提取數(shù)據(jù) |
圖 10-2 組件設(shè)計(jì)器中的“出題”應(yīng)用
按以下方式設(shè)置組件屬性:
1. 設(shè)置Text屬性:Label1為“問題:”,Label2為“答案:”,Label3為“試題及答案”;
2. 設(shè)置Label3的字號(hào)為18,并勾選FontBold屬性;
3. 設(shè)置QuestionText的Hint屬性為“輸入問題”,AnswerText的Hint屬性為“輸入回答”;
4. 設(shè)置SubmitButton的Text屬性為“提交”;
5. 設(shè)置QuestionsAnswersLabel的Text屬性為“試題及答案”;
6. 將QuestionText、AnswerText以及與它們相關(guān)的Label移入TableArrangement1。
在“總統(tǒng)測(cè)驗(yàn)”中,首先定義了兩個(gè)全局列表變量QuestionList和AnswerList,本章中無需為這兩個(gè)變量提供預(yù)設(shè)的問題和答案,如圖10-3所示。
圖 10-3 列表變量初始化
需要注意,與“總統(tǒng)測(cè)驗(yàn)“不同的是,這兩個(gè)列表沒有定義列表項(xiàng),因?yàn)椤俺鲱}”及“答題”應(yīng)用中,所有數(shù)據(jù)都將由用戶創(chuàng)建(即動(dòng)態(tài)的、用戶生成的數(shù)據(jù))。
首先來處理用戶的輸入行為。具體來說,當(dāng)用戶輸入問題和答案并點(diǎn)擊提交時(shí),程序要向列表中添加數(shù)據(jù)項(xiàng)來更新QuestionList和AnswerList,如下圖所示:
圖 10-4 向列表中添加新項(xiàng)
向列表中添加項(xiàng),意味著向列表的末尾追加新項(xiàng)。如圖10-4,程序從QuestionText和AnswerText文本框中獲取用戶輸入的內(nèi)容,并分別被追加到相應(yīng)的列表中。
向列表中添加的項(xiàng)更新了列表變量QuestionList和AnswerList,但用戶看不到任何變化。第三行的塊用來顯示這個(gè)變化:用冒號(hào)將兩個(gè)列表的內(nèi)容連接起來。默認(rèn)情況下,App Inventor用小括號(hào)來包圍列表內(nèi)容,列表項(xiàng)之間用空格間隔,像這樣:(item1 item2 item3)。當(dāng)然,這不是顯示列表的理想方式,只是暫時(shí)用來測(cè)試程序的行為。稍后我們將用更高級(jí)的方式來顯示列表,即,每對(duì)問題答案各占一行。
回憶一下在“總統(tǒng)測(cè)驗(yàn)”中,當(dāng)移動(dòng)到下一題時(shí),要清空上一題的回答結(jié)果。在本應(yīng)用中,當(dāng)用戶提交了一對(duì)問題-答案后,同樣要清空QuestionText及AnswerText文本框,以便準(zhǔn)備下一題的輸入,如下圖所示:
圖 10-5 提交問題-答案之后清空文本框
用戶提交的問題-答案,將分別被添加到各自的列表中,并顯示出來,這時(shí)QuestionText和AnswerText中的文本被清空,如圖10-5所示。請(qǐng)注意,可以復(fù)制一個(gè)有內(nèi)容的文本塊(如上圖中的“:”塊),通過刪除塊中的文本,來獲得一個(gè)空的文本塊。
現(xiàn)在是以App Inventor的默認(rèn)格式來顯示問題及答案。假如有一個(gè)有關(guān)州首府的測(cè)驗(yàn),已經(jīng)輸入了兩對(duì)問題-答案,則顯示成: (加州首府在哪? 紐約州首府在哪?):(薩克拉門托 奧爾巴尼)。
可以想像,如果測(cè)驗(yàn)中的問題很多,結(jié)果會(huì)顯得非?;靵y。理想的顯示方式,應(yīng)該是每行只顯示一對(duì)問題-答案:
加州首府在哪? 薩克拉門托
紐約州首府在哪? 奧爾巴尼
第20章講述了單個(gè)列表中項(xiàng)的逐行顯示技術(shù),在繼續(xù)學(xué)習(xí)之前,可以去閱讀一下。
這里的任務(wù)稍顯復(fù)雜,因?yàn)樯婕暗絻蓚€(gè)列表。為了應(yīng)對(duì)這種復(fù)雜性,需要?jiǎng)?chuàng)建過程displayQAs,并從SubmitButton.Click事件處理程序中調(diào)用該過程。
逐行顯示問題-答案,需要做到以下幾點(diǎn):
使用foreach塊遍歷QuestionList中的每個(gè)問題;
使用變量answerIndex,在遍歷問題的同時(shí),獲取與問題對(duì)應(yīng)的答案;
過程displayQAs封裝了所有用于顯示數(shù)據(jù)的塊,如圖10-6所示,在需要顯示列表時(shí),可直接調(diào)用displayQAs,而不必再重復(fù)使用過程內(nèi)部的塊。
圖 10-6 創(chuàng)建displayQAs過程
由于foreach塊只能遍歷一個(gè)列表,而本應(yīng)用中有兩個(gè)列表,因此要求在遍歷問題列表的同時(shí),為每個(gè)問題選擇對(duì)應(yīng)的答案。這需要定義一個(gè)索引變量,就像第8章“總統(tǒng)測(cè)試”中的currentQuestionIndex一樣,這里定義了answerIndex,當(dāng)foreach遍歷QuestionList時(shí),用來跟蹤對(duì)應(yīng)的答案在列表AnswerList中的位置。
在foreach開始遍歷之前,設(shè)answerIndex的值為1;在foreach遍歷過程中,answerIndex用來從AnswerList中選擇當(dāng)前問題的答案,然后遞增1。在foreach的每次迭代中,當(dāng)前的問題-答案被添加到QuestionsAnswersLabel的最后一行,問題與答案之間以冒號(hào)分隔。
已經(jīng)創(chuàng)建了顯示問題-答案的過程displayQAs,但在調(diào)用它之前,它起不到任何作用。修改SubmitButton.Click事件處理程序,用displayQAs替代對(duì)QuestionsAnswersLabel.Text的簡(jiǎn)單設(shè)置,來顯示所有的問題-答案。更新后的塊如圖10-7所示。
更多建議: