qooxdoo入門教程一:應用程式介面簡單設計
阿新 • • 發佈:2019-01-29
視窗執行配置
教程的最後一個任務就是配置視窗。在開啟視窗時視窗的顯示位置在瀏覽器的左上角,很不好看,為了將視窗的顯示位置離開瀏覽器的邊緣。需要在您的應用程式新增以下程式碼:
main.moveTo(50,30);
//main.center(); //視窗居中顯示
另外我們應該配置視窗的控制按鈕。讓使用者不能關閉、最小化和最大化視窗。在視窗的建構函式中新增以下程式碼:
this.setShowClose(false);
this.setShowMaximize(false);
this.setShowMinimize(false);
最後一件事就是改變啟動時視窗的大小。當然,執行時使用者也可以改變視窗的大小,但是為了啟動應用程式就有一個好看的視窗,應該在程式啟動時設定視窗的初始大小。改變視窗大小和隱藏控制按鈕一樣容易,只是在視窗的建構函式加入如下程式碼:
this.setWidth(250);
this.setHeight(300);
這時執行程式,您的應用程式應該像下圖這樣。
由於以上程式碼沒有增加新的類的呼叫,所以應用不需要呼叫generate.py命令。
我們需要做的第下一件事情就是為我們的視窗設定一個元件佈局。 在上面的介面中你可以看到文字區域和按鈕並排在一行而其它所有元素垂直排列。但是,所有的元素都可以看做在網格中對齊排列的,因此我們選擇為當前視窗選擇一個網格佈局。在我們的視窗類中新增網格佈局,就是在MainWindow.js檔案中新增下面這些程式碼:
var layout = new qx.ui.layout.Grid(0,0);
this.setLayout(layout);
沒有任何內容的佈局是沒有意義的,所以下面給佈局新增一些內容,看看它是否正常執行。讓我們新增系統的前兩個元素Toolbar和List View到窗口布局中。
Layout和Toolbar
我們需要在新增工具欄前建立它。建立工具欄並將其直接新增到佈局中。
var toolbar = new qx.ui.toolbar.ToolBar();
this.add(toolbar, {row: 0, column: 0});
上面的程式碼就將工具欄新增到主視窗的網格佈局中。 你唯一需要注意的事情就是add()函式的第二個引數。它包含了佈局屬性的位置資訊。你可以在Layout API中查詢在這種網格佈局情況下可用的佈局屬性,在這裡,我們只使用row和column兩個屬性來告訴佈局toolbar位於網格佈局的第一行、第一列(row和column以0開始)。
Layout和List
新增List到佈局的程式碼看起來很熟悉。
// list
var list = new qx.ui.form.List();
this.add(list, {row: 1, column: 0});
現在在瀏覽器中看看我們的工作效果。同樣的,在程式碼中我們增加了新的類,它需要新的依賴關係,因此我們需要呼叫generate.py生成器來重新生成程式碼。之後,我們就可以在瀏覽器中看到結果了。但這我們看到的結果卻不是我們想要的樣子,看不到Toolbar,List與視窗邊框有太多的填充而且也沒有充滿整個視窗。這些事項都我們需要考慮的。
首先,我們不需要List與視窗邊框之間的填充。解決這個問題我們中需要修改window物件的一個預設的內容填充屬性即可。
this.setContentPadding(0);
將這一行程式碼加入到主視窗的建構函式中,填充就去除了。
接下來,我們需要考慮List的大小。Layout並不知道哪一列(幾列)或哪一行(幾行)應該擴充套件。為此我們需要告訴Layout:
layout.setRowFlex(1, 1);
layout.setColumnFlex(0, 1);
程式碼第一行告訴Layout第二行(也就是List所在行)大小需要擴充套件。第二行程式碼對Layout的第一列執行相同的設定。
我們需要做的最後一件事就是解決Toolbar不可見的問題。如果你知道Toolbar不可見的原因,你肯定也知道怎麼解決。原因就是Toolbar沒有包含任何一個元件所以它看不到,下面我們給它加入一個元件。在我們教程的這個例子中,我們需要新增一個重新整理按鈕。我們已經知道如何建立和新增元件,所以只需要在檔案中新增以下程式碼。
var reloadButton = new qx.ui.toolbar.Button("Reload");
toolbar.add(reloadButton);
現在看看所有的修改就否都完成了,記住一定要在重新載入瀏覽器頁面之前在執行程式碼生成器,因為我們以增加了一個新的類(button)。我們看到的結果正是我們想要的樣子。
TextArea 和Button
在以上面容成功後,我們可以繼續進行下一個任務了,新增Text Area和“Post”按鈕,象前在的場景一樣直接新增它們。
// textarea
var textarea = new qx.ui.form.TextArea();
this.add(textarea, {row: 2, column: 0});
// post button
var postButton = new qx.ui.form.Button("Post");
this.add(postButton, {row: 2, column: 1});
這一次,我們在佈局的第二列新增一個POST的按鈕,並使其與TextArea水平對齊。再次生成並重新載入進行測試。
像上次一樣,顯示結果並不是我們希望的樣子。Toolbar和List沒有填滿整個視窗。不要僅,這是一個我們自己的問題,因為我們新增按鈕的動作將Layout擴大到了兩列。 List和Toolbar需要跨越兩列才能得到我們想要的結果。這很容易,在向佈局中新增List和Toolbar控制元件時使用一個合併單元格的佈局屬性colSpan:2。程式碼應該是下面這樣:
this.add(toolbar, {row: 0, column: 0, colSpan: 2});
this.add(list, {row: 1, column: 0, colSpan: 2});
為UI新增動作
現在的使用者介面看起來就是我們想要的。 但如何將UI與應用程式的後臺邏輯程式碼進行溝通呢? 使用事件通知的方式將UI與程式邏輯處理分離就是一個好方法。如果你仔細看就會發現我們的應用只需要UI向後臺邏輯傳送兩個事件通知:過載Tweets和發一個Tweet。
我們新增這兩個事件到視窗中。 新增事件分為兩步。 首先,我們需要宣告想要觸發什麼樣的事件。 因此,我們視窗類定義的建構函式中加事件定義部分:
events :
{
"reload" : "qx.event.type.Event",
"post" : "qx.event.type.Data"
},
正如你看到的程式碼,它逗號結束。是否需要以逗號結尾取決於你將程式碼複製在什麼位置,你只需確定這個類的定義是一個有效的JavaScript物件就可以了。現在再回到事件中,reload事件是一個普通的事件,只是通知接收器重新載入。post事件需要將包含的資料釋出到identica中,是一個數據事件,這就是為什麼需要使用兩種不同型別的事件。
宣告該事件是使用事件的第一步驟。 第二個步驟就是觸發事件!讓我們來看看在過載事件,在載入按鈕被觸發(qooxdoo的說法是執行)時執行這個過載事件。按鈕本身有觸發執行事件,所以我們可以使用按鈕本身的觸發執行事件來觸發我們自定義的過載事件。
reloadButton.addListener("execute", function() {
this.fireEvent("reload");
}, this);
這裡,我們做了兩件事情:第一新增一個事件監聽器,第二觸發一個事件就象呼叫一個方法一樣簡單。 fireEvent()唯一的引數是我們在類定義中宣告的事件的名稱。另一個有趣的事情是addListener函式的第三個引數this。它設定在我們的視窗例項中回撥函式要使用的上下文物件,因此this.fireEvent()中的this才能被正確解析。
接下來的程式碼雖有一些不同,但也很容易。
postButton.addListener("execute", function() {
this.fireDataEvent("post", textarea.getValue());
}, this);
這一次,我們使用fireDataEvent方法對資料事件進行觸發。這個方法的第二個引數就是這個資料事件中需要嵌入的資料。在這裡我們只是簡單地使用文字區域的值。為了測試這兩個事件,我們需為每個事件在我們的應用程式程式碼中新增一個除錯監聽器,在application.js的main()方法加入下面程式碼:
main.addListener("reload", function() {
this.debug("reload");
}, this);
main.addListener("post", function(e) {
this.debug("post: " + e.getData());
}, this);
在這兩個事件中我們使用了qooxdoo除錯功能中的debug函式。現在我們可以對整個使用者介面進行測試了。使用一個你喜歡的瀏覽器開啟索引檔案,就會看到UI的效果。如果想看到的除錯資訊,你必須開啟你所選擇瀏覽器中的除錯工具或者使用qooxdoo的除錯控制檯。 按F7可以使qooxdoo控制檯可見。
結束工作
在這個任務的最後,我們可以對使用者介面進行一些完善。如果文字區域有一些文字告訴你應該在這裡輸入你的資訊,工具欄顯示一些提示資訊告訴使用者一些更詳細資訊?這樣使用者介面就顯的更加友好了。達到上面的目的非常容易!
reloadButton.setToolTipText("Reload the tweets.");
textarea.setPlaceholder("Enter your message here...");
postButton.setToolTipText("Post this message on identi.ca");
另外一個很好的設定就是在視窗標題欄中加入一個Identica的Logo。只要從identica網上下載一個Logo的PNG圖示,將其儲存在的應用程式的source/resource/tweets目錄中。為視窗新增圖示是容易的因為視窗有一個新增圖示的屬性,你可以在視窗的建構函式中設定這個屬性。
this.base(arguments, "tweets", "tweets/logo.png");
這一次,我們以增加了一個新的影象。影象類的也需要依賴關係,因此我們需要再次執行程式碼生成器。然後,就可以在windows的標題欄中看到影象了。
下面還有兩個小的改動需要來完成。 首先,按鈕看起來不怎麼好。因此我們應該給它一個固定的寬度,並讓它的高度自適應。
postButton.setWidth(60);
最後一個任務相對與前面的調整有些複雜。你可能知道,identica資訊最大隻能有140個字元。所有輸入的資訊超過140個字元時候應該禁用POST按鈕,這樣可以幫助後臺通訊層更好的執行。 完全沒有文字的identica訊息也是不可用的,那麼在在這種情況下也應該禁用POST按鈕。為了得到我們想要的效果,當文字區域中的文字被改變的時候應該通知我們進行一些設定,幸運的是,文字區域有一個文字變化的資料事件,下面我們來監聽這個事件:
textarea.addListener("input", function(e) {
var value = e.getData();
postButton.setEnabled(value.length < 140 && value.length > 0);
}, this);
這個事件處理程式只有兩行,首先取得文字區域中更改的文字內容。第二行根據文字內容長度是否超過140或長度為0來設定POST按鈕的enabled屬性。有些人可能感覺這些程式碼不好,因為使用者每新增一個字元監聽器就會被呼叫一次, 但這不是一個問題,因為qooxdoo屬性系統已經考慮到了,如果傳入的setter的值與現有的值一樣,它會被忽略也不會觸發事件。
我們考試的最後一件事是應用程式啟動時。文字區是空的,但POST按鈕中有效的。因此我們要禁止按鈕。
postButton.setEnabled(false);
教程的最後一個任務就是配置視窗。在開啟視窗時視窗的顯示位置在瀏覽器的左上角,很不好看,為了將視窗的顯示位置離開瀏覽器的邊緣。需要在您的應用程式新增以下程式碼:
main.moveTo(50,30);
//main.center(); //視窗居中顯示
另外我們應該配置視窗的控制按鈕。讓使用者不能關閉、最小化和最大化視窗。在視窗的建構函式中新增以下程式碼:
this.setShowClose(false);
this.setShowMaximize(false);
this.setShowMinimize(false);
最後一件事就是改變啟動時視窗的大小。當然,執行時使用者也可以改變視窗的大小,但是為了啟動應用程式就有一個好看的視窗,應該在程式啟動時設定視窗的初始大小。改變視窗大小和隱藏控制按鈕一樣容易,只是在視窗的建構函式加入如下程式碼:
this.setWidth(250);
this.setHeight(300);
這時執行程式,您的應用程式應該像下圖這樣。
由於以上程式碼沒有增加新的類的呼叫,所以應用不需要呼叫generate.py命令。
我們需要做的第下一件事情就是為我們的視窗設定一個元件佈局。 在上面的介面中你可以看到文字區域和按鈕並排在一行而其它所有元素垂直排列。但是,所有的元素都可以看做在網格中對齊排列的,因此我們選擇為當前視窗選擇一個網格佈局。在我們的視窗類中新增網格佈局,就是在MainWindow.js檔案中新增下面這些程式碼:
var layout = new qx.ui.layout.Grid(0,0);
this.setLayout(layout);
沒有任何內容的佈局是沒有意義的,所以下面給佈局新增一些內容,看看它是否正常執行。讓我們新增系統的前兩個元素Toolbar和List View到窗口布局中。
Layout和Toolbar
我們需要在新增工具欄前建立它。建立工具欄並將其直接新增到佈局中。
var toolbar = new qx.ui.toolbar.ToolBar();
this.add(toolbar, {row: 0, column: 0});
上面的程式碼就將工具欄新增到主視窗的網格佈局中。 你唯一需要注意的事情就是add()函式的第二個引數。它包含了佈局屬性的位置資訊。你可以在Layout API中查詢在這種網格佈局情況下可用的佈局屬性,在這裡,我們只使用row和column兩個屬性來告訴佈局toolbar位於網格佈局的第一行、第一列(row和column以0開始)。
Layout和List
新增List到佈局的程式碼看起來很熟悉。
// list
var list = new qx.ui.form.List();
this.add(list, {row: 1, column: 0});
現在在瀏覽器中看看我們的工作效果。同樣的,在程式碼中我們增加了新的類,它需要新的依賴關係,因此我們需要呼叫generate.py生成器來重新生成程式碼。之後,我們就可以在瀏覽器中看到結果了。但這我們看到的結果卻不是我們想要的樣子,看不到Toolbar,List與視窗邊框有太多的填充而且也沒有充滿整個視窗。這些事項都我們需要考慮的。
首先,我們不需要List與視窗邊框之間的填充。解決這個問題我們中需要修改window物件的一個預設的內容填充屬性即可。
this.setContentPadding(0);
將這一行程式碼加入到主視窗的建構函式中,填充就去除了。
接下來,我們需要考慮List的大小。Layout並不知道哪一列(幾列)或哪一行(幾行)應該擴充套件。為此我們需要告訴Layout:
layout.setRowFlex(1, 1);
layout.setColumnFlex(0, 1);
程式碼第一行告訴Layout第二行(也就是List所在行)大小需要擴充套件。第二行程式碼對Layout的第一列執行相同的設定。
我們需要做的最後一件事就是解決Toolbar不可見的問題。如果你知道Toolbar不可見的原因,你肯定也知道怎麼解決。原因就是Toolbar沒有包含任何一個元件所以它看不到,下面我們給它加入一個元件。在我們教程的這個例子中,我們需要新增一個重新整理按鈕。我們已經知道如何建立和新增元件,所以只需要在檔案中新增以下程式碼。
var reloadButton = new qx.ui.toolbar.Button("Reload");
toolbar.add(reloadButton);
現在看看所有的修改就否都完成了,記住一定要在重新載入瀏覽器頁面之前在執行程式碼生成器,因為我們以增加了一個新的類(button)。我們看到的結果正是我們想要的樣子。
TextArea 和Button
在以上面容成功後,我們可以繼續進行下一個任務了,新增Text Area和“Post”按鈕,象前在的場景一樣直接新增它們。
// textarea
var textarea = new qx.ui.form.TextArea();
this.add(textarea, {row: 2, column: 0});
// post button
var postButton = new qx.ui.form.Button("Post");
this.add(postButton, {row: 2, column: 1});
這一次,我們在佈局的第二列新增一個POST的按鈕,並使其與TextArea水平對齊。再次生成並重新載入進行測試。
像上次一樣,顯示結果並不是我們希望的樣子。Toolbar和List沒有填滿整個視窗。不要僅,這是一個我們自己的問題,因為我們新增按鈕的動作將Layout擴大到了兩列。 List和Toolbar需要跨越兩列才能得到我們想要的結果。這很容易,在向佈局中新增List和Toolbar控制元件時使用一個合併單元格的佈局屬性colSpan:2。程式碼應該是下面這樣:
this.add(toolbar, {row: 0, column: 0, colSpan: 2});
this.add(list, {row: 1, column: 0, colSpan: 2});
為UI新增動作
現在的使用者介面看起來就是我們想要的。 但如何將UI與應用程式的後臺邏輯程式碼進行溝通呢? 使用事件通知的方式將UI與程式邏輯處理分離就是一個好方法。如果你仔細看就會發現我們的應用只需要UI向後臺邏輯傳送兩個事件通知:過載Tweets和發一個Tweet。
我們新增這兩個事件到視窗中。 新增事件分為兩步。 首先,我們需要宣告想要觸發什麼樣的事件。 因此,我們視窗類定義的建構函式中加事件定義部分:
events :
{
"reload" : "qx.event.type.Event",
"post" : "qx.event.type.Data"
},
正如你看到的程式碼,它逗號結束。是否需要以逗號結尾取決於你將程式碼複製在什麼位置,你只需確定這個類的定義是一個有效的JavaScript物件就可以了。現在再回到事件中,reload事件是一個普通的事件,只是通知接收器重新載入。post事件需要將包含的資料釋出到identica中,是一個數據事件,這就是為什麼需要使用兩種不同型別的事件。
宣告該事件是使用事件的第一步驟。 第二個步驟就是觸發事件!讓我們來看看在過載事件,在載入按鈕被觸發(qooxdoo的說法是執行)時執行這個過載事件。按鈕本身有觸發執行事件,所以我們可以使用按鈕本身的觸發執行事件來觸發我們自定義的過載事件。
reloadButton.addListener("execute", function() {
this.fireEvent("reload");
}, this);
這裡,我們做了兩件事情:第一新增一個事件監聽器,第二觸發一個事件就象呼叫一個方法一樣簡單。 fireEvent()唯一的引數是我們在類定義中宣告的事件的名稱。另一個有趣的事情是addListener函式的第三個引數this。它設定在我們的視窗例項中回撥函式要使用的上下文物件,因此this.fireEvent()中的this才能被正確解析。
接下來的程式碼雖有一些不同,但也很容易。
postButton.addListener("execute", function() {
this.fireDataEvent("post", textarea.getValue());
}, this);
這一次,我們使用fireDataEvent方法對資料事件進行觸發。這個方法的第二個引數就是這個資料事件中需要嵌入的資料。在這裡我們只是簡單地使用文字區域的值。為了測試這兩個事件,我們需為每個事件在我們的應用程式程式碼中新增一個除錯監聽器,在application.js的main()方法加入下面程式碼:
main.addListener("reload", function() {
this.debug("reload");
}, this);
main.addListener("post", function(e) {
this.debug("post: " + e.getData());
}, this);
在這兩個事件中我們使用了qooxdoo除錯功能中的debug函式。現在我們可以對整個使用者介面進行測試了。使用一個你喜歡的瀏覽器開啟索引檔案,就會看到UI的效果。如果想看到的除錯資訊,你必須開啟你所選擇瀏覽器中的除錯工具或者使用qooxdoo的除錯控制檯。 按F7可以使qooxdoo控制檯可見。
結束工作
在這個任務的最後,我們可以對使用者介面進行一些完善。如果文字區域有一些文字告訴你應該在這裡輸入你的資訊,工具欄顯示一些提示資訊告訴使用者一些更詳細資訊?這樣使用者介面就顯的更加友好了。達到上面的目的非常容易!
reloadButton.setToolTipText("Reload the tweets.");
textarea.setPlaceholder("Enter your message here...");
postButton.setToolTipText("Post this message on identi.ca");
另外一個很好的設定就是在視窗標題欄中加入一個Identica的Logo。只要從identica網上下載一個Logo的PNG圖示,將其儲存在的應用程式的source/resource/tweets目錄中。為視窗新增圖示是容易的因為視窗有一個新增圖示的屬性,你可以在視窗的建構函式中設定這個屬性。
this.base(arguments, "tweets", "tweets/logo.png");
這一次,我們以增加了一個新的影象。影象類的也需要依賴關係,因此我們需要再次執行程式碼生成器。然後,就可以在windows的標題欄中看到影象了。
下面還有兩個小的改動需要來完成。 首先,按鈕看起來不怎麼好。因此我們應該給它一個固定的寬度,並讓它的高度自適應。
postButton.setWidth(60);
最後一個任務相對與前面的調整有些複雜。你可能知道,identica資訊最大隻能有140個字元。所有輸入的資訊超過140個字元時候應該禁用POST按鈕,這樣可以幫助後臺通訊層更好的執行。 完全沒有文字的identica訊息也是不可用的,那麼在在這種情況下也應該禁用POST按鈕。為了得到我們想要的效果,當文字區域中的文字被改變的時候應該通知我們進行一些設定,幸運的是,文字區域有一個文字變化的資料事件,下面我們來監聽這個事件:
textarea.addListener("input", function(e) {
var value = e.getData();
postButton.setEnabled(value.length < 140 && value.length > 0);
}, this);
這個事件處理程式只有兩行,首先取得文字區域中更改的文字內容。第二行根據文字內容長度是否超過140或長度為0來設定POST按鈕的enabled屬性。有些人可能感覺這些程式碼不好,因為使用者每新增一個字元監聽器就會被呼叫一次, 但這不是一個問題,因為qooxdoo屬性系統已經考慮到了,如果傳入的setter的值與現有的值一樣,它會被忽略也不會觸發事件。
我們考試的最後一件事是應用程式啟動時。文字區是空的,但POST按鈕中有效的。因此我們要禁止按鈕。
postButton.setEnabled(false);