天天看點

《互動式程式設計 第2版》一3.5 捕獲簡單使用者互動行為

本節書摘來華章計算機《互動式程式設計 第2版》一書中的第3章 ,第3.5節,joshua noble 著 毛順兵 張婷婷 陳宇 沈鑫 任燦江 譯更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

從頭開始說起吧。最基本的使用者互動模式有兩種:滑鼠和鍵盤。下面介紹processing是如何處理這兩種互動的。要捕獲這兩種互動,你需要知道滑鼠何時移動,滑鼠按鍵何時按下,滑鼠何時拖動(即按住按鍵不放并移動滑鼠),是否有鍵盤按鍵被按下,如果有的話,被按下的是哪個鍵。與這些相關的方法和變量是現成的,就存在于processing應用程式中。你隻需要使用它們,也就是說,你隻需要告訴processing系統,當某個方法被調用時你想做什麼事情,或者當方法被調用或在draw()方法中時你想通路什麼變量。

内置變量mousex和mousey是滑鼠目前位置坐标,機關是像素。如果滑鼠在視窗客戶區的左上角,那麼mousex和mousey都是0。如果滑鼠在視窗右下角,并且視窗大小是300像素×300像素,那麼mousex和mousey都是299。通過這兩個内置變量,你任何時候都可以獲得滑鼠位置。示例3-9中,每次draw()被調用,都輸出滑鼠位置。

示例3-9:fonts.pde

從代碼注釋可以看出,該程式不僅使用到滑鼠位置,而且用text()方法将滑鼠位置作為文本輸出到螢幕上滑鼠處。這裡用到了text()方法,它有3個參數:

第一個參數是字元串,第二個和第三個參數是字元串顯示位置,它們可以是float型或int型。在前面的例子中,字元串位置被設定為滑鼠位置,即變量mousex和mousey。

processing應用程式有一個方法叫mousepressed()。如果應用程式獲得焦點,那麼每當使用者按下滑鼠上任何按鍵,就會執行該回調方法。當然,前面說過,如果沒有draw()方法,那麼mousepressed()方法是不會執行的。

示例3-10用幾個繪圖方法示範了如何使用mousepressed()方法。

示例3-10:mpressed.pde

使用者按下滑鼠的某個鍵時,mousepressed()方法執行,它将設定填充色的alpha值設定為滑鼠x坐标。draw()被不斷調用,它用修改後的alpha值構造填充色,畫出的矩形的填充色也就發生了改變。

當使用者放開滑鼠按鍵,mousereleased()方法會被執行。和mousepressed()類似,你可以在mousereleased()方法中放置一些代碼,以便在滑鼠按鍵放開時執行。mousedragged()方法也如此,但它是在使用者拖動滑鼠(按住滑鼠按鍵并移動滑鼠)時被調用的。在滑鼠驅動的應用程式中,常常在mousedragged()方法中将一個布爾型變量設定為真,以表示正在拖動滑鼠。示例3-11中,在mousedragged()方法中放置了繪圖代碼。

示例3-11:dragged.pde

這是一個簡單的繪圖程式。用變量存儲上一次滑鼠的位置,當拖動滑鼠時,在上一次位置和滑鼠目前位置之間畫線。運作這個程式,然後将draw()方法中給lastx和lasty指派的兩條語句注釋掉,再運作,看看有什麼變化。

即便不要那兩條指派語句,也有别的簡單辦法來實作自由畫線,那就是使用變量pmousex和pmousey。它們是程式前一幀的滑鼠位置。下面的代碼就使用了這兩個變量:

延伸一下,你現在可以編寫這樣一個複雜一些的程式:當使用者在程式視窗中點選時,以這些點選的位置為頂點畫出圖形。這個代碼示例有幾個代碼段,你需要一個一個地閱讀。第一段是定義一個類。

首先,你要寫出單詞class和類名(如point),以及一個左大括号。左大括号表示你即将開始定義方法和資料。

class point{

然後,定義兩個變量來存放點的坐标。

下面是該類的構造函數。

這個構造函數有兩個形參_x和_y,它執行時會把這兩個傳遞進來的參數值賦給x和y。一個point類的具體執行個體(對象)是點,可以存放使用者滑鼠點選的位置。

既然點類point已經定義好,現在可以建立若幹個點對象。假設我們最多允許繪制六邊形,為了存儲6個點,就需要建立一個點數組,它的每個元素都是一個點的執行個體。

還要做的一件事情是編寫mousepressed()方法,以便在滑鼠按下時,将mousex和mousey儲存在點數組中。另外,還要在draw()方法中利用這些點繪制多邊形。示例3-12中,由于程式較為複雜,故特意将它劃分成多個步驟。

示例3-12:point.pde

在draw()方法中,用background()方法将背景色設定為白色,用fill()方法将填充色設定為黑色,然後用for循環來繪制那些點構成的多邊形:

一開始的時候,點數組pts中的每個元素都是null。為了避免錯誤,對于每個元素,都需要確定它是點的執行個體才能将它納入到多邊形頂點中:

如果它不是null,可以用它來建立一個頂點:

結束繪圖:

當使用者按下滑鼠,要将滑鼠位置存儲到pts數組中備用。具體怎麼做呢?可以建立一個新的point對象,并将目前的mousex和mousey傳遞給它,并将這個對象存儲到pts數組中第count個元素那個位置:

好了。再寫一遍point類的完整聲明:

那麼,當你在程式視窗中點選時發生了什麼?修改point類的構造函數:

如此一來,每當你在程式視窗中點選時,你将會看到在控制台輸出一行資訊(當然,具體資料跟你點選的位置有關):

那麼,這一切是怎麼發生的呢?再看看mousepressed()方法:

每當使用者按下滑鼠按鍵時,mousepressed()方法被調用執行。它調用point類的構造函數,建立了一個點對象,并将mousex和mousey傳遞給這個點。然後将這個點存儲到pts數組中,以便draw()方法能使用這些點對象來建立多邊形頂點。

前面的例子用到了for循環、類、數組以及vertex()方法。該代碼示例有些難度,需要認真思考才能了解。第5章将介紹關于類的更多内容。

你或許想知道使用者是否按了鍵盤鍵。你可以判斷使用者是否按鍵,并且可以獲知使用者按下了哪個鍵。要實作這個目的,有兩種方式。第一種是在draw()方法中檢查keypressed變量:

注意,你可以通過key變量來判斷使用者按下了哪個鍵。processing應用程式将每個鍵都存儲在内置變量中。此外,processing還定義了一個keypressed()方法,當使用者按鍵時,這個方法會被調用。你可以像使用mousepressed()或mousemoved()方法一樣來使用keypressed()方法:

處理按鍵的程式代碼都應該放到keypressed()方法中。例如,遊戲中使用者按下方向鍵,或者使用者在一個文本框中輸入名字後按下了Enter鍵。

注意: keypressed()是一個方法,而keypressed是一個屬性(變量)。它們除了名字相同之外,其他方面有很大差別。隻有當使用者按鍵時,keypressed()方法才會被調用執行;而如果對keypressed變量的檢測是在draw()循環中進行的,你按鍵的時間是在兩次draw()執行的空檔,那麼程式是檢測不到的。

訪談:ben fry

ben fry和casey reas同為processing項目的發起人。ben fry在全球很多地方都做過關于資料可視化、媒體藝術和計算機科學的演講。他還出版了兩本書,一本是《processing: a programming handbook for visual designers and artists》(由他和casey reas合著,麻省理工學院出版社),另一本是《visualizing data》(o扲eilly出版社)。另外他還建立了大量的資料可視化作品、圖表,并撰寫了不少論文。

是什麼令你對資料可視化産生興趣的?是出于審美考慮,還是為了解決資料處理的問題,抑或兩者皆有?

ben: 都有。在年少時我就對平面設計和計算機科學産生了興趣:我在中學時就覺得廣告、标志和排印很有趣,而編寫我的第一個basic程式還要更早。讀大學時,我學習平面設計,尤其喜歡資訊設計(和動畫以及動态資訊顯示)。有很長一段時間,我以為我會一直從事ui設計,事實上我的實習和第一份工作都是這個方面的。然而事實并非如此,在麻省理工學院研究所學生院,我将設計和可視化結合在一起。實際上,在學校裡我的學習重點主要是平面設計,以及少量計算機科學(至少大學是這樣)。設計是主要科目,因為我認為它會給我帶來更多的靈活性以及教我如何去思考。我被領向計算藝術,由于它融合了這兩個(當時)完全不同的興趣點。沮喪了幾個月,我意識到我不再是跨學科的了,因為我的兩個感興趣學科融合了。好的一面是,我可以專注于這種直接的融合;而不好的一面是,我不能像年輕時想的那樣去單獨對待這兩個學科了。

我覺得你的工作中有一個中心思想,那就是關于設計師在社會、科學、計算以及其他方面如何定位的問題,在那些方面,視覺設計通常被當做次要因素。這種評價正确嗎?在其他那些低估了視覺設計價值的地方,你認為視覺設計還是必需的嗎?

ben: 事實确實如此,凡事有兩面。首先,社會、科學、計算這些方面是我最喜歡和好奇的。其次,務實地說,對那些問題感興趣的人越來越少,是以我能為自己開辟出一個新的方向。

看到你所做的工作,我經常會有“哇哦”這樣的反應。起初,視覺的美感和複雜性确實震撼了我,接着我才意識到什麼是可視化。這些工作是你有目的地做的,還是你早已聽聞,或本身就很想做的?

ben: 人們傾向于要麼讓事物更美,要麼讓它們更有資訊含量,很少把它們放在一起考慮。尤其是在處理資訊的時候,這種非此即彼的态度更是随處可見。但是除非有東西兼具這兩種特性,否則我不太會感覺滿意。我希望一個項目在得到一聲“喔”的驚歎以後,仍然是有價值的。但是,那些漂亮的部分其實很容易做出來。在某種程度上,我僅僅處理那些我想看的東西,我希望它們不僅有視覺刺激,還有思維上的刺激。當然,這就進入了一個十分主觀的領域,而且,我也不願意把我的作品當做“美麗的東西”——那種意見很個人化,閱聽人有可能同意,也有可能不同意。如果我的工作在人們面前隻得到一聲“喔”,随後什麼也沒有,我會認為這是一種失敗。如果一幅圖沒有讓人們好奇到想要深入挖掘,沒有讓人們對其主題産生好奇,那麼我就沒做好我的工作(至少在我看來是這樣)。

一件像“aligning humans and animals”這樣的圖形塊既是一個很好的例證,也是對大量資訊的合理、科學、嚴謹的暗示。這樣一來,它讓我想起了一些當代藝術家(想到卡斯滕·尼古拉)。他們處理複雜的概念,使它們醒目和易讀。您能否談談令您感到振奮的一些當代藝術家或設計師?

看你在部落格上寫的文章還有你寫的書,你涉及的主題極為廣泛——從排印到棒球選手,再到政府和隐私的插圖——但這些資料似乎都一團糟。你有沒有方法來尋找主題?

ben: 這在很大程度上隻是出于好奇,但這對我來說是組織我的思想的方式。我不喜歡讓我的部落格、著作等與我的工作直接相關(它們往往會混淆我的想法),但我從來都不知道為什麼會這樣。在組織思想時,我很容易了解什麼是其中最主要的。在一定程度上,這既能提高寫作能力,也對健康有益。

至于方法,我努力堅持圍繞資訊和資料的主題,但偏向電影和運動一些,通常是因為它涉及繪圖(與通信有關)或叙述(可視化)。遠離政治,或者說,遠離上周的“周六夜現場”中的太空奧運會獨幕喜劇,這對我是很難的,但我不想掉進大衆喜好的圈子,也不希望我的部落格是流水賬。

你是否認為你的設計工作可能讓你遠離資訊可視化并通往更具抽象審美的東西,或者你對資訊類的東西不感興趣?

ben: 不,我想我反而是太沉迷于資訊。它可能帶我遠離設計,并進入我們如何看待資料的那些方面(例如,沿着部落格上一串關于隐私和安全的博文,弄清楚“我們擁有這些資料,現在該怎麼辦?”)。但我同樣喜歡視覺方面,是以我認為我不會完全放棄它。

開發processing,有多少原因是你自己缺乏一個類似的工具,有多少因素是由于想為他人開發工具,這兩者你怎麼看?

ben: 嗯,我認為,起初這兩個原因同等重要,但後來更多地是讓processing成為大家的工具。為陌生人開發一個工具所花的時間比為自己開發工具要多幾個數量級。就算如此,我們也要把公共的部分做完(即便常常對我們自己的工作有影響)。

也就是說,它在很大程度上受我自己的工作的驅動——常常是我自己的開發中用到了一些新東西,然後立即或者很快就去改進processing。說實話,我們在有些地方(如聲音)做得不夠好,因為casey和我在我們自己的工作中都沒有充分利用它們。

我認為,processing更多地是一種“回饋”項目。在我10歲或12歲學習程式設計時,很多人把他們的程式代碼共享給我(無論直接還是間接),我很感激他們。processing項目也是開放的,有能力的人可以将它往前推進。偶爾我看到用processing開發出來的作品時,我想過放棄自己開發項目,而更加努力地開發processing。

作為一個程式員,我真的很喜歡反編譯和程式修正,因為這兩個不同的過程都圍繞着一件事,那就是代碼的開發和運作。您怎麼看?

ben: 它們都跟人們腦海中的想象有關……我大緻能夠想象出代碼随時間變化的樣子,以及正在運作的代碼的樣子,但我真的很想看到。我懷疑,得到其他人良好反應的圖像未必具有特别的開創性(我們以前看過視覺差異和代碼跟蹤),這有點像看到一個夢想的實作,或閱讀的一篇文章完美地表達了你的看法,比如對一個複雜的政治局勢或社會現象的看法。

關于processing的未來,你有一個清晰的願景嗎?還是規模大又活躍的processing社群在一定意義上幫助引導該項目?

ben: 我認為社群已經在很多決策上引導我們了。如果你看看我們在項目剛開始時的目标(線上的web傳輸,再加上支援象串行i/o這樣的功能、硬體裝置等),再看看項目現在的情況(完整的應用程式、圖形加速和許許多多的庫),你會發現那隻“看不見的手”的确在推動。

一些最近的事态發展都與在其他語言(javascript、ruby和python)中使用api有關,起初這并非真的可行,但我真的很興奮。現在社群真的把它拿過來用了。

是不是有各種各樣的項目,人們并沒有真正用processing深入處理,而你又希望人們那樣做?

ben: casey和我在這個項目中的個人目标之一是,如果我們讓容易的事情變得更容易,讓困難的事情不那麼難,那麼項目的總體品質水準也許能提高一些,或者換句話說,你可以避免很多由于不專業而引發的問題。我認為我們還沒有做到我期望的那種成功。

你怎麼想到要為非程式員創造一門語言?是ruby或python這些“友好”的語言引發的?還是由你想象中的使用者要做的事情驅使?或者是發明教學語言的想法促成的?

ben: 這些因素都有,另外還有我們積累的偏好,以及基于過去經曆的嚴苛意見。

但可以肯定的是,我們還沒有建立出一個最終的語言門類,我們隻是試圖将我們知道的內建在一起,并把它朝我們認為正确的那個方向推進。如果想要有革命性的改變,我認為文法和構思模型就得大改。但我們必須衡量實際(人們接受它離現有語言多遠,以及我們建立的軟體需要運作多快)。

除了分析資料、了解資料的認知過程,你也可以讓使用者與它互動工作。你覺得,與資料互動的觀念同易讀和廣博地顯示資料的觀念是一樣豐富的領域嗎?

ben: 哦,那絕對是一個豐富的領域,因為它更多地涉及我們的感官和身體。有一些事情是要盯着看的,我們抓住并操縱、移動它們,看它們做什麼(如同看着一個6個月大的嬰兒)。 做得越多,我們就能學得越多。

繼續閱讀