Google Web Toolkit(GWT)是一個用於創建富網際網路應用程式(RIA)的開發工具包。以下是它的一些顯著特點;
GWT爲開發人員提供了用JAVA編寫客戶端應用程式的選項。
GWT將用JAVA編寫的代碼編譯成JavaScript代碼。
用GWT編寫的應用程式是跨瀏覽器兼容的。GWT自動生成適合每個瀏覽器的javascript代碼。
GWT是開源的,完全免費的,全世界成千上萬的開發人員都在使用它。它是在Apache許可版本2.0下授權的。
總的來說,GWT是一個框架來構建大規模、高性能的web應用程式,同時使它們易於維護。
Why to use GWT?
由於是基於Java的,您可以使用類似Eclipse的javaide來開發GWT應用程式。
開發人員可以使用代碼自動完成/重構/導航/項目管理和IDEs.GWT的所有特性,這些特性提供了完整的調試功能。開發人員可以像調試Java應用程式一樣調試客戶端應用程式。
GWT提供了與Junit和Maven的簡單集成。
同樣是基於Java的,GWT對於Java開發人員來說學習曲線很低。
GWT生成優化的javascript代碼,自行生成瀏覽器的特定javascript代碼。
GWT提供了Widgets庫,它提供了應用程式中所需的大部分任務。
GWT是可擴展的,可以創建自定義小部件來滿足應用程式的需要。
最重要的是,GWT應用程式可以在所有主流瀏覽器和智慧型手機上運行,包括基於Android和iOS的手機/平板電腦。
Disadvantages of GWT
儘管GWT有很多優點,但它有以下缺點;
由GWT生成的不可索引網頁不會被搜尋引擎索引,因爲這些應用程式是動態生成的。
不可降解−如果應用程式用戶禁用Javascript,則用戶將只看到基本頁,而不看到其他內容。
不是設計器友好的−GWT不適合那些喜歡使用帶有占位符的純HTML在稍後時間插入動態內容的web設計器。
The GWT Components
GWT框架可以分爲以下三個主要部分&負;
GWT Java到JavaScript編譯器−這是GWT最重要的部分,它是構建ria的強大工具。GWT編譯器用於將所有用Java編寫的應用程式代碼轉換爲JavaScript。
JRE仿真庫−Google Web Toolkit包含一個模擬Java運行時庫子集的庫。列表包括java.lang、java.lang.annotation、java.math、java.io、java.sql、java.util和java.util.logging
GWT UI building library這部分由許多子部分組成,包括實際的UI組件、RPC支持、歷史管理等等。
GWT還提供了一個GWT託管的Web瀏覽器,它允許您在託管模式下運行和執行GWT應用程式,在這種模式下,您的代碼在Java虛擬機中作爲Java運行,而無需編譯爲JavaScript。
GWT - Environment Setup
本教程將指導您如何準備開發環境以開始使用GWT框架。本教程還將教您如何在設置GWT框架之前在計算機上設置JDK、Tomcat和Eclipse−
System Requirement
GWT要求JDK 1.6或更高版本,所以第一個要求是在您的機器中安裝JDK。
JDK | 1.6 or above. |
---|---|
Memory | no minimum requirement. |
Disk Space | no minimum requirement. |
Operating System | no minimum requirement. |
按照給定的步驟設置環境以開始GWT應用程式開發。
Step 1 - Verify Java Installation on your Machine
現在打開console並執行以下java命令。
OS | Task | Command |
---|---|---|
窗口 | Open Command Console | c:\> java -version |
linux/ | Open Command Terminal | $ java -version |
麥克 | Open Terminal | machine:~ joseph$ java -version |
讓我們驗證所有作業系統的輸出
Sr.No. | OS & Generated Output |
---|---|
1 |
窗口 java版本「1.6.0_21」 Java(TM)SE運行時環境(構建1.6.0_21-b07) Java HotSpot(TM)客戶端虛擬機(構建17.0-b17,混合模式,共享) |
2 |
linux/ java版本「1.6.0_21」 Java(TM)SE運行時環境(構建1.6.0_21-b07) ava HotSpot(TM)客戶端虛擬機(內部版本17.0-b17,混合模式,共享) |
3 |
麥克 java版本「1.6.0_21」 Java(TM)SE運行時環境(構建1.6.0_21-b07) Java HotSpot(TM)64位伺服器虛擬機(內部版本17.0-b17,混合模式,共享) |
Step 2 - Setup Java Development Kit (JDK)
如果您沒有安裝Java,那麼可以從Oracle的Java站點安裝Java軟體開發工具包(SDK):Java SE下載。您將在下載的文件中找到安裝JDK的說明,按照給定的說明安裝和配置安裝程序。最後設置PATH和JAVA_HOME環境變量來引用包含JAVA和javac的目錄,通常分別是JAVA_install_dir/bin和JAVA_install_dir。
將環境變量設置爲指向機器上安裝JAVA的基本目錄位置。例如
Sr.No. | OS & Output |
---|---|
1 |
窗口 將環境變量JAVA_HOME設置爲C:\ Program Files\JAVA\jdk1.6.0_21 |
2 |
linux/ 將JAVA導出到HOME=/usr/local/JAVA current |
3 |
麥克 導出JAVA_HOME=/Library/JAVA/HOME |
將Java編譯器位置附加到系統路徑。
Sr.No. | OS & Output |
---|---|
1 |
窗口 將字符串%JAVA_HOME%\bin追加到系統變量Path的末尾。 |
2 |
linux/ 導出路徑=$PATH:$JAVA_HOME/bin/ |
3 |
麥克 不需要的 |
或者,如果您使用集成開發環境(IDE),如Borland JBuilder、Eclipse、IntelliJ IDEA或Sun ONE Studio,請編譯並運行一個簡單的程序,以確認IDE知道您在哪裡安裝了Java,否則請按照IDE的給定文檔進行正確的設置。
Step 3 - Setup Eclipse IDE
本教程中的所有示例都是使用EclipseIDE編寫的。所以我建議您應該根據您的作業系統在您的計算機上安裝最新版本的Eclipse。
要安裝EclipseIDE,請從https://www.Eclipse.org下載最新的Eclipse二進位文件。下載安裝後,將二進位發行版解壓縮到一個方便的位置。例如在windows上的C:\ eclipse中,或者在Linux/Unix上的/usr/local/eclipse中,最後適當地設置PATH變量。
可以通過在windows機器上執行以下命令啓動Eclipse,也可以雙擊Eclipse.exe
%C:\eclipse\eclipse.exe
Eclipse可以通過在Unix(Solaris、Linux等)機器上執行以下命令來啓動−
$/usr/local/eclipse/eclipse
成功啓動後,如果一切正常,則應顯示以下結果&負;
Step 4 - Install GWT SDK & Plugin for Eclipse
按照連結Plugin for Eclipse(包括SDK)中提供的說明,在您的計算機上安裝用於Eclipse版本的GWT SDK&Plugin。
在成功設置了GWT插件之後,如果一切正常,那麼它應該在下面的螢幕上顯示帶有紅色矩形標記的Google圖標,如下所示;
Step 5: Setup Apache Tomcat
您可以從https://Tomcat.apache.org/「target=」\blank「>https://Tomcat.apache.org/下載最新版本的Tomcat。下載安裝後,將二進位發行版解壓縮到一個方便的位置。例如,在windows上的C:\ apache-tomcat-6.0.33中,或在Linux/Unix上的/usr/local/apache-tomcat-6.0.33中,並將CATALINA_HOME環境變量設置爲指向安裝位置。
Tomcat可以通過在windows機器上執行以下命令來啓動,也可以雙擊startup.bat
%CATALINA_HOME%\bin\startup.bat or /usr/local/apache-tomcat-6.0.33/bin/startup.sh
成功啓動後,通過訪問http://localhost:8080/可以使用Tomcat中包含的默認web應用程式。如果一切正常,那麼它應該顯示以下結果&負;
有關配置和運行Tomcat的更多信息,請參閱此處的文檔以及Tomcat網站−https://Tomcat.apache.org/
在windows機器上執行以下命令可以停止Tomcat−
%CATALINA_HOME%\bin\shutdown or C:\apache-tomcat-5.5.29\bin\shutdown
可以通過在Unix(Solaris、Linux等)機器上執行以下命令來停止Tomcat−
$CATALINA_HOME/bin/shutdown.sh or /usr/local/apache-tomcat-5.5.29/bin/shutdown.sh
GWT - Applications
在我們開始使用GWT創建實際的「HelloWorld」應用程式之前,讓我們看看GWT應用程式的實際部分是什麼;
GWT應用程式由以下四個重要部分組成,其中最後一部分是可選的,前三部分是必需的。
- Module descriptors
- Public resources
- Client-side code
- Server-side code
典型gwt應用程式的不同部分的樣本位置如下所示;
Name | Location |
---|---|
Project root | HelloWorld/ |
Module descriptor | src/com/tutorialspoint/HelloWorld.gwt.xml |
Public resources | src/com/tutorialspoint/war/ |
Client-side code | src/com/tutorialspoint/client/ |
Server-side code | src/com/tutorialspoint/server/ |
Module Descriptors
模塊描述符是XML格式的配置文件,用於配置GWT應用程式。
模塊描述符文件擴展名是*.gwt.xml,其中*是應用程式的名稱,該文件應位於項目的根目錄中。
下面是HelloWorld應用程式的默認模塊描述符HelloWorld.gwt.xml−
<?xml version = "1.0" encoding = "utf-8"?> <module rename-to = 'helloworld'> <!-- inherit the core web toolkit stuff. --> <inherits name = 'com.google.gwt.user.user'/> <!-- inherit the default gwt style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- specify the paths for translatable code --> <source path = '...'/> <source path = '...'/> <!-- specify the paths for static files like html, css etc. --> <public path = '...'/> <public path = '...'/> <!-- specify the paths for external javascript files --> <script src = "js-url" /> <script src = "js-url" /> <!-- specify the paths for external style sheet files --> <stylesheet src = "css-url" /> <stylesheet src = "css-url" /> </module>
下面是模塊描述符中使用的不同部分的簡要詳細信息。
Sr.No. | Nodes & Description |
---|---|
1 |
<module rename to=「helloworld」> 這提供了應用程式的名稱。 |
2 |
<繼承name=「logical module name」/> 這將在應用程式中添加其他gwt模塊,就像import在java應用程式中所做的那樣。可以用這種方式繼承任意數量的模塊。 |
3 |
<entry point class=「classname」/> 它指定將開始加載GWT應用程式的類的名稱。可以添加任意數量的入口點類,並按它們在模塊文件中出現的順序順序依次調用它們。因此,當第一個入口點的onModuleLoad()完成時,將立即調用下一個入口點。 |
4 |
<source path=「path」/> 它指定GWT編譯器將搜索原始碼編譯的源文件夾的名稱。 |
5 |
<public path=「path」/> 公共路徑是項目中存儲GWT模塊引用的靜態資源(如CSS或圖像)的位置。默認的公共路徑是存儲模塊XML文件的公共子目錄。 |
6 |
<script src=「js url」/> 自動注入位於src指定位置的外部JavaScript文件。 |
7 |
<樣式表src=「css url」/> 自動插入位於src指定位置的外部CSS文件。 |
Public Resources
這些都是GWT模塊引用的文件,例如宿主HTML頁面、CSS或圖像。
可以使用模塊配置文件中的<public path=「path」/>元素配置這些資源的位置。默認情況下,它是存儲模塊XML文件的公共子目錄。
將應用程式編譯爲JavaScript時,可以在公共路徑上找到的所有文件都將複製到模塊的輸出目錄中。
最重要的公共資源是用於調用實際GWT應用程式的主機頁。應用程式的典型HTML宿主頁可能根本不包含任何可見的HTML正文內容,但它總是希望通過以下<script…/>標記包含GWT應用程式
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Hello World</h1> <p>Welcome to first GWT application</p> </body> </html>
下面是我們在主頁中包含的樣式表示例;
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
Client-side Code
這是實現應用程式業務邏輯的實際Java代碼,GWT編譯器將其轉換爲JavaScript,最終在瀏覽器中運行。可以使用模塊配置文件中的<source path=「path」/>元素配置這些資源的位置。
例如,入口點代碼將用作客戶端代碼,其位置將使用<source path=「path」/>指定;。
模塊入口點是任何可分配給入口點且無需參數即可構造的類。加載模塊時,將實例化每個入口點類,並調用其entry point.onModuleLoad()方法。示例HelloWorld入口點類如下所示−
public class HelloWorld implements EntryPoint { public void onModuleLoad() { Window.alert("Hello, World!"); } }
Server-side Code
這是應用程式的伺服器端部分,而且非常可選。如果在應用程式中不使用進行任何後端處理,則不需要此部分,但如果後端需要進行某些處理,並且客戶端應用程式與伺服器交互,則必須開發這些組件。
下一章將使用上述所有概念來使用EclipseIDE創建HelloWorld應用程式。
GWT - Create Application
由於GWT的威力在於用Java編寫,用JavaScript運行,我們將使用Java IDE Eclipse演示我們的示例。
讓我們從一個簡單的HelloWorld應用程式開始−
Step 1 - Create Project
第一步是使用EclipseIDE創建一個簡單的Web應用程式項目。使用選項啓動項目嚮導Google Icon>新建Web應用程式項目…。現在使用嚮導窗口將您的項目命名爲HelloWorld,如下所示−
取消選擇「使用Google應用程式引擎」,因爲我們沒有在此項目中使用它,並保留其他默認值(保持選中「生成示例項目代碼」選項),然後單擊「完成」按鈕。
成功創建項目後,您的項目資源管理器中將包含以下內容−
以下是所有重要文件夾的簡要說明
Sr.No. | Folder & Location |
---|---|
1 |
src公司 原始碼(java類)文件。 包含負責客戶端UI顯示的客戶端特定java類的客戶端文件夾。 包含負責伺服器端處理的伺服器端java類的伺服器文件夾。 包含java模型類的共享文件夾,用於將數據從伺服器傳輸到客戶端,反之亦然。 HelloWorld.gwt.xml,gwt編譯器編譯HelloWorld項目所需的模塊描述符文件。 |
2 |
測試 測試代碼(java類)源文件。 包含負責測試gwt客戶端代碼的java類的客戶機文件夾。 |
3 |
戰爭 這是最重要的部分,它代表了實際的可部署web應用程式。 包含編譯類、gwt庫、servlet庫的WEB-INF。 css,項目樣式表。 HelloWorld.html,hots html將調用GWT UI應用程式。 |
Step 2 - Modify Module Descriptor: HelloWorld.gwt.xml
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. You can change --> <!-- the theme of your GWT application by uncommenting --> <!-- any one of the following lines. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- <inherits name = 'com.google.gwt.user.theme.chrome.Chrome'/> --> <!-- <inherits name = 'com.google.gwt.user.theme.dark.Dark'/> --> <!-- Other module inherits --> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
Step 3 - Modify Style Sheet: HelloWorld.css
GWT插件將創建一個默認的樣式表文件war/HelloWorld.css。讓我們修改這個文件,使我們的示例保持在最簡單的理解級別−
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
Step 4 - Modify Host File: HelloWorld.html
GWT插件將創建一個默認的HTML主機文件war/HelloWorld.HTML。讓我們修改這個文件,使我們的示例保持在最簡單的理解級別−
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Hello World</h1> <p>Welcome to first GWT application</p> </body> </html>
您可以在同一個源目錄中創建更多的靜態文件,如HTML、CSS或圖像,也可以創建更多的子目錄並在這些子目錄中移動文件,並在應用程式的模塊描述符中配置這些子目錄。
Step 5 - Modify Entry Point: HelloWorld.java
讓我們修改這個文件以顯示「你好,世界!」
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window; public class HelloWorld implements EntryPoint { public void onModuleLoad() { Window.alert("Hello, World!"); } }
您可以在同一個源目錄中創建更多的Java文件來定義入口點或定義幫助程序例程。
Step 6 - Compile Application
一旦您準備好所有的更改,就可以編譯項目了。使用選項Google Icon>gwt Compile Project…啓動gwt Compile對話框,如下所示−
保持默認值不變,然後單擊「編譯」按鈕。如果一切順利,您將在Eclipse控制台中看到以下輸出
Compiling module com.tutorialspoint.HelloWorld Compiling 6 permutations Compiling permutation 0... Compiling permutation 1... Compiling permutation 2... Compiling permutation 3... Compiling permutation 4... Compiling permutation 5... Compile of permutations succeeded Linking into C:\workspace\HelloWorld\war\helloworld Link succeeded Compilation succeeded -- 33.029s
Step 7 - Run Application
現在點擊run application菜單並選擇HelloWorld來運行應用程式。
如果一切正常,您必須看到GWT開發模式在Eclipse中處於活動狀態,其中包含如下所示的URL。雙擊URL以打開GWT應用程式。
因爲您正在開發模式下運行應用程式,所以您需要爲瀏覽器安裝GWT插件。只需按照螢幕上的說明安裝插件。
如果您已經爲瀏覽器設置了GWT插件,那麼您應該能夠看到以下輸出
祝賀 你!您已經使用Google Web Toolkit(GWT)實現了第一個應用程式。
GWT - Deploy Application
本教程將向您介紹如何創建一個應用程式「war」文件,以及如何在Apache Tomcat Websever根目錄中部署該文件。
如果您理解這個簡單的示例,那麼您還可以按照相同的步驟部署複雜的GWT應用程式。
讓我們使用Eclipse IDE和GWT插件,並按照以下步驟創建GWT應用程式−
Step | Description | 1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
---|---|
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to make sure business logic is working as per the requirements. |
4 | Finally, zip the content of the war folder of the application in the form of war file and deploy it in Apache Tomcat Webserver. |
5 | Launch your web application using appropriate URL as explained below in the last step. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Hello World</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { HTML html = new HTML("<p>Welcome to GWT application</p>"); RootPanel.get("gwtContainer").add(html); } }
在這裡,我們創建了基本的widgest HTML,並將其添加到具有id=「gwtContainer」的div標記中。在接下來的章節中,我們將研究不同的GWT小部件。
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
Create WAR File
現在我們的應用程式運行良好,我們準備將其導出爲war文件。
請遵循以下步驟&負;
Go into your project's 戰爭 directory C:\workspace\HelloWorld\war
選擇war目錄中可用的所有文件和文件夾。
壓縮名爲HelloWorld.Zip的文件中的所有選定文件和文件夾。
將HelloWorld.zip重命名爲HelloWorld.war。
Deploy WAR file
停止tomcat伺服器。
將HelloWorld.war文件複製到tomcat installation directory>webapps文件夾
啓動tomcat伺服器。
在webapps目錄中,應該有一個文件夾helloworld已創建。
現在HelloWorld.war已經成功地部署在Tomcat Webserver根目錄中。
Run Application
在web瀏覽器中輸入url:http://localhost:8080/HelloWorld以啓動應用程式
伺服器名(localhost)和埠(8080)可能因tomcat配置而異。
GWT - Style with CSS
GWT小部件依賴於層疊樣式表(CSS)進行視覺樣式設置。默認情況下,每個組件的類名都是gwt-<class name>。
例如,Button小部件的默認樣式爲gwt Button,TextBox widgest的默認樣式爲gwt TextBox。
爲了給所有按鈕和文本框一個更大的字體,您可以在應用程式的CSS文件中放置以下規則
.gwt-Button { font-size: 150%; } .gwt-TextBox { font-size: 150%; }
默認情況下,瀏覽器和GWT都不會爲小部件創建默認的id屬性。必須顯式地爲可以在CSS中使用的元素創建唯一id。爲了給一個idmy button idb>的按鈕一個更大的字體,您可以在應用程式的CSS文件中放置以下規則−
#my-button-id { font-size: 150%; }
要設置GWT小部件的id,請檢索其DOM元素,然後按以下方式設置id屬性−
Button b = new Button(); DOM.setElementAttribute(b.getElement(), "id", "my-button-id")
CSS Styling APIs
對於任何GWT小部件,都有許多api可用於hangle CSS設置。以下是一些重要的api,它們可以幫助您使用GWT−進行日常的web編程;
Sr.No. | API & Description |
---|---|
1 |
public void setStyleName(java.lang.String樣式) 此方法將清除任何現有樣式,並將窗口小部件樣式設置爲使用樣式提供的新CSS類。 |
2 |
public void addStyleName(java.lang.String樣式) 此方法將向小部件添加輔助樣式名或從屬樣式名。輔助樣式名是一個附加樣式名,即,如果應用了任何以前的樣式名,則保留這些名稱。 |
3 |
public void removeStyleName(java.lang.String樣式) 此方法將從小部件中移除給定的樣式,並保留與小部件關聯的任何其他樣式。 |
4 |
公共java.lang.String getStyleName() 此方法以空格分隔的列表形式獲取對象的所有樣式名。 |
5 |
public void setStylePrimaryName(java.lang.String樣式) 此方法設置對象的主樣式名並更新所有從屬樣式名。 |
例如,讓我們定義兩種新樣式,我們將應用於文本;
.gwt-Big-Text { font-size:150%; } .gwt-Small-Text { font-size:75%; } .gwt-Red-Text { color:red; }
現在您可以使用setStyleName(Style)將默認設置更改爲新設置。應用以下規則後,文本的字體將變大
txtWidget.setStyleName("gwt-Big-Text");
我們可以在同一個小部件上應用第二個CSS規則來更改其顏色,如下所示−
txtWidget.addStyleName("gwt-Red-Text");
使用上面的方法,您可以添加任意多的樣式來應用於小部件。如果從按鈕小部件中刪除第一個樣式,則第二個樣式仍將保留在文本中。
txtWidget.removeStyleName("gwt-Big-Text");
Primary & Secondary Styles
默認情況下,小部件的primary style名稱將是其小部件類的默認樣式名稱,例如按鈕小部件的gwt Button。當我們使用AddStyleName()方法添加和刪除樣式名時,這些樣式稱爲輔助樣式。
小部件的最終外觀由添加到它的所有次要樣式加上它的主要樣式的總和決定。使用setStylePrimaryName(String)方法設置小部件的主樣式。舉例來說,假設我們有一個Label小部件。在CSS文件中,我們定義了以下規則−
.MyText { color: blue; } .BigText { font-size: large; } .LoudText { font-weight: bold; }
假設我們希望特定的標籤小部件始終顯示藍色文本,並且在某些情況下,使用更大的粗體字體來增加強調。
我們可以這樣做;
// set up our primary style Label someText = new Label(); someText.setStylePrimaryName("MyText"); ... // later on, to really grab the user's attention someText.addStyleName("BigText"); someText.addStyleName("LoudText"); ... // after the crisis is over someText.removeStyleName("BigText"); someText.removeStyleName("LoudText");
Associating CSS Files
將CSS文件與模塊關聯有多種方法。現代GWT應用程式通常使用CssResource和UiBinder的組合。在我們的例子中,我們只使用第一種方法。
在宿主HTML頁中使用「連結」標記。
使用模塊XML文件中的<樣式表>元素。
使用aClientBundle中包含的aCssResource。
使用aui活頁夾模板中的內聯<ui:style>元素。
GWT CSS Example
This example will take you through simple steps to apply different CSS rules on your GWT widgest. 讓我們使用Eclipse IDE和GWT插件,並按照以下步驟創建GWT應用程式−
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; } .gwt-Button { font-size: 150%; font-weight: bold; width:100px; height:100px; } .gwt-Big-Text { font-size:150%; } .gwt-Small-Text { font-size:75%; }
下面是修改後的HTML宿主文件的內容,可以容納兩個按鈕。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <div id = "mytext"><h1>Hello, World!</h1></div> <div id = "gwtGreenButton"></div> <div id = "gwtRedButton"></div> </body> </html>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { // add button to change font to big when clicked. Button Btn1 = new Button("Big Text"); Btn1.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { RootPanel.get("mytext").setStyleName("gwt-Big-Text"); } }); // add button to change font to small when clicked. Button Btn2 = new Button("Small Text"); Btn2.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { RootPanel.get("mytext").setStyleName("gwt-Small-Text"); } }); RootPanel.get("gwtGreenButton").add(Btn1); RootPanel.get("gwtRedButton").add(Btn2); } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
現在試著點擊顯示的兩個按鈕並觀察「你好,世界!」在點擊兩個按鈕時不斷改變字體的文本。
GWT - Basic Widgets
每個用戶界面都考慮以下三個主要方面;
UI元素是用戶最終看到並與之交互的核心視覺元素。GWT提供了大量廣泛使用的通用元素,從基本元素到複雜元素,我們將在本教程中介紹這些元素。
布局−它們定義了UI元素在螢幕上的組織方式,並爲GUI(圖形用戶界面)提供了最終的外觀。本部分將在布局章節中介紹。
行爲−這些是用戶與UI元素交互時發生的事件。本部分將在事件處理章節中介紹。
GWT UI Elements
GWT庫在定義良好的類層次結構中提供類,以創建複雜的基於web的用戶界面。此組件層次結構中的所有類都是從UIObject基類派生的,如下所示−
每個基本的UI小部件都從widget類繼承屬性,而widget類又從UIObject繼承屬性。樹和菜單將在複雜的小部件教程中介紹。
Sr.No. | Widget & Description |
---|---|
1 |
GWT UIObject Class
此小部件包含文本,而不是使用<div>元素解釋爲HTML,從而使其以塊布局顯示。 |
2 |
GWT Widget Class
此小部件可以包含HTML文本,並使用<div>元素顯示HTML內容,從而使其以塊布局顯示。 |
Basic Widgets
以下是一些重要的基本小部件;
Sr.No. | Widget & Description |
---|---|
1 |
Label
此小部件包含文本,而不是使用<div>元素解釋爲HTML,從而使其以塊布局顯示。 |
2 |
HTML
此小部件可以包含HTML文本,並使用<div>元素顯示HTML內容,從而使其以塊布局顯示。 |
3 |
Image
此小部件在給定的URL處顯示圖像。 |
4 |
Anchor
此小部件表示一個簡單的元素。 |
GWT - Form Widgets
表單小部件允許用戶輸入數據,並爲他們提供與應用程式的交互功能。每個表單小部件都從小部件類繼承屬性,而小部件類又從UIObject和Wigdet類繼承屬性。
Sr.No. | Widget & Description |
---|---|
1 |
GWT UIObject Class
此小部件包含文本,而不是使用<div>元素解釋爲HTML,從而使其以塊布局顯示。 |
2 |
GWT Widget Class
此小部件可以包含HTML文本,並使用<div>元素顯示HTML內容,從而使其以塊布局顯示。 |
Form Widgets
以下是一些重要的窗體小部件;
Sr.No. | Widget & Description |
---|---|
1 |
Button
這個小部件代表一個標準的按鈕。 |
2 |
PushButton
此小部件表示具有自定義樣式的普通按鈕。 |
3 |
ToggleButton
這個小部件表示一個時髦的有狀態按鈕,允許用戶在上下狀態之間切換。 |
4 |
CheckBox
此小部件表示標準複選框小部件。這個類還用作單選按鈕的基類。 |
5 |
RadioButton
此小部件表示一個互斥的選擇單選按鈕小部件。 |
6 |
ListBox
這個小部件向用戶表示一個選項列表,可以是列表框,也可以是下拉列表。 |
7 |
SuggestBox
此小部件表示一個文本框或文本區域,其中顯示與用戶輸入匹配的一組預先配置的選擇。每個SuggestBox都與一個SuggestOracle相關聯。SuggestOracle用於提供給定特定查詢字符串的一組選擇。 |
8 |
TextBox
此小部件表示單行文本框。 |
9 |
PasswordTextBox
此小部件表示一個文本框,該文本框可視地屏蔽其輸入以防止竊聽。。 |
10 |
TextArea
此小部件表示允許輸入多行文本的文本框。 |
11 |
RichTextArea
這個小部件代表一個富文本編輯器,允許複雜的樣式和格式。 |
12 |
FileUpload
此小部件包裝HTML<input type='file'>元素。 |
13 |
Hidden
此小部件在HTML表單中表示隱藏欄位。 |
GWT - Complex Widgets
「複雜窗口小部件」允許用戶與應用程式進行高級交互功能。每個複雜的小部件都從小部件類繼承屬性,而小部件類又從UIObject繼承屬性。
Sr.No. | Widget & Description |
---|---|
1 |
GWT UIObject Class
此小部件包含文本,而不是使用<div>元素解釋爲HTML,從而使其以塊布局顯示。 |
2 |
GWT Widget Class
此小部件可以包含HTML文本,並使用<div>元素顯示HTML內容,從而使其以塊布局顯示。 |
Complex Widgets
以下是一些重要的複雜小部件−
Sr.No. | Widget & Description |
---|---|
1 |
Tree
這個小部件代表一個標準的層次樹小部件。樹包含一個樹狀結構,用戶可以打開、關閉和選擇。 |
2 |
MenuBar
這個小部件代表一個標準的菜單欄小部件。菜單欄可以包含任意數量的菜單項,每個菜單項都可以啓動命令或打開級聯菜單欄。 |
3 |
DatePicker
這個小部件代表一個標準的GWT日期選擇器。 |
4 |
CellTree
此小部件表示樹的視圖。這個小部件只能在標準模式下工作,這要求運行它的HTML頁面具有顯式<!DOCTYPE>聲明。 |
5 |
CellList
此小部件表示單元格的單列列表。 |
6 |
CellTable
此小部件表示支持分頁和列的表格視圖。 |
7 |
CellBrowser
此小部件表示樹的可瀏覽視圖,在該視圖中,每個級別一次只能打開一個節點。這個小部件只能在標準模式下工作,這要求運行它的HTML頁面具有顯式<!DOCTYPE>聲明。 |
GWT - Layout Panels
布局面板可以包含其他小部件。這些面板控制小部件在用戶界面上的顯示方式。每個Panel小部件從Panel類繼承屬性,Panel類又從widget類繼承屬性,Panel類又從UIObject類繼承屬性。
Sr.No. | Widget & Description |
---|---|
1 |
GWT UIObject Class
此小部件包含文本,而不是使用<div>元素解釋爲HTML,從而使其以塊布局顯示。 |
2 |
GWT Widget Class
此小部件可以包含HTML文本,並使用<div>元素顯示HTML內容,從而使其以塊布局顯示。 |
3 |
GWT Panel Class
這是所有面板的抽象基類,這些面板是可以包含其他小部件的小部件。 |
Layout Panels
以下是幾個重要的布局面板;
Sr.No. | Widget & Description |
---|---|
1 |
FlowPanel
此小部件表示一個面板,該面板使用默認的HTML布局行爲格式化其子小部件。 |
2 |
HorizontalPanel
這個小部件表示一個面板,它將所有小部件放在一個水平列中。 |
3 |
VerticalPanel
這個小部件表示一個面板,它將所有小部件放在一個垂直列中。 |
4 |
HorizontalSplitPanel
此小部件表示一個面板,該面板將兩個小部件排列在一個水平行中,並允許用戶交互更改專用於兩個小部件的寬度比例。必要時,包含在水平拆分面板中的小部件將自動用滾動條裝飾。 |
5 |
VerticalSplitPanel
這個小部件表示一個面板,它將兩個小部件排列在一個垂直列中,並允許用戶交互地更改兩個小部件的高度比例。必要時,VertialSplitPanel中包含的小部件將自動用滾動條裝飾。 |
6 |
FlexTable
這個小部件表示一個靈活的表,可以根據需要創建單元格。它可以是鋸齒形的(即,每一行可以包含不同數量的單元格),單個單元格可以設置爲跨多行或多列。 |
7 |
Grid
這個小部件表示一個矩形網格,它可以在單元格中包含文本、html或子小部件。它必須顯式地調整到所需的行數和列數。 |
8 |
DeckPanel
在一個「deck」中顯示其所有子窗口小部件的面板,其中一次只能看到一個窗口小部件。它由TabPanel使用。 |
9 |
DockPanel
這個小部件代表一個面板,它將其子小部件「停靠」在外部邊緣,並允許其最後一個小部件占據其中心的剩餘空間。 |
10 |
HTMLPanel
這個小部件代表一個包含HTML的面板,它可以將子小部件附加到HTML中標識的元素。 |
11 |
TabPanel
此小部件表示一個面板,該面板表示一組帶選項卡的頁面,每個頁面都包含另一個小部件。當用戶選擇與之關聯的各個選項卡時,它的子窗口小部件就會顯示出來。選項卡可以包含任意HTML。 |
12 |
Composite
此小部件表示一種可以包裝另一個小部件的小部件,隱藏包裝的小部件的方法。當添加到面板時,組合的行爲與它包裝的小部件被添加的行爲完全相同。 |
13 |
SimplePanel
此小部件表示僅包含一個小部件的面板的基類。 |
14 |
ScrollPanel
這個小部件表示一個簡單的面板,它將其內容包裝在一個可滾動的區域中 |
15 |
FocusPanel
這個小部件代表一個簡單的面板,使其內容可聚焦,並增加了捕捉滑鼠和鍵盤事件的能力。 |
16 |
FormPanel
此小部件表示一個將其內容包裝在HTML<FORM>元素中的面板。 |
17 |
PopupPanel
這個小部件代表一個可以在其他小部件上彈出的面板。它覆蓋瀏覽器的工作區(以及以前創建的任何彈出窗口)。 |
18 |
DialogBox
這個小部件代表一種彈出窗口,頂部有一個標題區域,用戶可以拖動它。與popupanel不同,調用popupanel.set width(String)和popupanel.set height(String)將設置對話框本身的寬度和高度,即使尚未添加小部件。 |
GWT - Event Handling
GWT提供了一個類似於Java AWT或SWING用戶界面框架的事件處理程序模型。
監聽器接口定義了一個或多個小部件調用以宣布事件的方法。GWT提供了對應於各種可能事件的接口列表。
希望接收特定類型事件的類實現關聯的處理程序接口,然後將對自身的引用傳遞給小部件以訂閱一組事件。
例如,按鈕類發布單擊事件,因此您必須編寫一個類來實現單擊處理程序來處理單擊事件。
Event Handler Interfaces
所有GWT事件處理程序都從event handler接口擴展而來,每個處理程序只有一個帶有單個參數的方法。此參數始終是關聯事件類型的對象。每個事件對象都有許多方法來操作傳遞的事件對象。例如,對於click事件,您必須按以下方式編寫處理程序−
/** * create a custom click handler which will call * onClick method when button is clicked. */ public class MyClickHandler implements ClickHandler { @Override public void onClick(ClickEvent event) { Window.alert("Hello World!"); } }
現在,任何希望接收click事件的類都將調用addClickHandler()來註冊一個事件處理程序,如下所示−
/** * create button and attach click handler */ Button button = new Button("Click Me!"); button.addClickHandler(new MyClickHandler());
每個支持事件類型的小部件都有一個HandlerRegistration addFoo處理程序(Foo事件)的方法,其中Foo是實際的事件,如單擊、錯誤、按鍵等。
下面是重要的GWT事件處理程序和相關事件以及處理程序註冊方法的列表;
Sr.No. | Event Interface | Event Method & Description |
---|---|---|
1 | Before Selection Handler<I> |
選擇前無效(選擇事件前<I>事件) 在啓動BeforeSelectionEvent時調用。 |
2 | BlurHandler |
void on blur( 在啓動模糊事件時調用。 |
3 | ChangeHandler |
更改時無效(ChangeEvent事件) 在激發更改事件時調用。 |
4 | ClickHandler |
單擊即作廢(ClickEvent事件) 在激發本機單擊事件時調用。 |
5 | CloseHandler<T> |
關閉時無效(關閉事件<T>事件) 在啓動CloseEvent時調用。 |
6 | Context Menu Handler |
Void on context menu( 在激發本機上下文菜單事件時調用。 |
7 | Double Click Handler |
Void on double click( 在觸發雙擊事件時調用。 |
8 | Error Handler |
出錯時無效(錯誤事件事件) 在觸發錯誤事件時調用。 |
9 | Focus Handler |
焦點無效(焦點事件事件) 啓動焦點事件時調用。 |
10 | Form Panel.Submit Complete Handler |
提交完成時作廢(表單面板。提交完整事件事件) 成功提交表單時激發。 |
11 | FormPanel.SubmitHandler |
提交時無效(表單面板。提交事件事件事件) 提交表單時激發。 |
12 | Key Down Handler |
void on key down(>key down event event) 在觸發KeyDownEvent時調用。 |
13 | KeyPressHandler |
void on keypress( 在啓動KeyPressEvent時調用。 |
14 | KeyUpHandler |
void on keyup( 在觸發KeyUpEvent時調用。 |
15 | LoadHandler |
加載時無效(LoadEvent事件) 在啓動LoadEvent時調用。 |
16 | MouseDownHandler |
MouseDown上的void(MouseDown event事件) 當MouseDown被解僱時調用。 |
17 | MouseMoveHandler |
MouseMove上的void(mousemovevent事件) 當MouseMoveEvent被激發時調用。 |
18 | MouseOutHandler |
MouseOut上的void(MouseOut event事件) 當MouseOutEvent被觸發時調用。 |
19 | MouseOverHandler |
MouseOver時無效(MouseOver event事件) 在觸發MouseOverEvent時調用。 |
20 | MouseUpHandler |
MouseUp上的void(MouseUp event事件) 當MouseUpEvent被解僱時調用。 |
21 | MouseWheelHandler |
滑鼠滾輪上的空白(滑鼠滾輪事件事件) 當mouseweelevent被激發時調用。 |
22 | ResizeHandler |
調整大小時無效(ResizeEvent事件) 調整小部件大小時激發。 |
23 | ScrollHandler |
void on scroll( 在觸發ScrollEvent時調用。 |
24 | SelectionHandler<I> |
選擇無效(SelectionEvent<I>事件) 在啓動SelectionEvent時調用。 |
25 | ValueChangeHandler<I> |
值更改時無效(ValueChangeEvent<I>事件) 在觸發ValueChangeEvent時調用。 |
26 | Window.ClosingHandler |
窗口關閉時無效(Window.ClosingEvent事件) 在瀏覽器窗口關閉或導航到其他站點之前激發。 |
27 | Window.ScrollHandler |
WindowScroll上的void(Window.ScrollEvent事件) 在滾動瀏覽器窗口時激發。 |
Event Methods
如前所述,每個處理程序都有一個帶有單個參數的方法來保存事件對象,例如void onClick(ClickEvent event)或void onKeyDown(keydownext event)。像ClickEvent和KeyDownEvent這樣的事件對象很少有下面列出的常用方法−
Sr.No. | Method & Description |
---|---|
1 |
protected void dispatch(ClickHandler handler)此方法只能由HandlerManager調用 |
2 |
doEvent.Type<FooHandler>getAssociatedType()此方法返回用於註冊Foo事件的類型。 |
3 |
static DomEvent.Type<FooHandler>getType()此方法獲取與Foo事件關聯的事件類型。 |
4 |
public java.lang.Object getSource()此方法返回上次觸發此事件的源。 |
5 |
protected final boolean is live()此方法返回事件是否處於活動狀態。 |
6 |
protected void kill()此方法終止事件 |
Example
本例將引導您通過簡單的步驟來展示如何在GWT中使用aClick事件和KeyDown事件處理。按照以下步驟更新我們在GWT-Create application−一章中創建的GWT應用程式;
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Event Handling Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { /** * create textbox and attach key down handler */ TextBox textBox = new TextBox(); textBox.addKeyDownHandler(new MyKeyDownHandler()); /* * create button and attach click handler */ Button button = new Button("Click Me!"); button.addClickHandler(new MyClickHandler()); VerticalPanel panel = new VerticalPanel(); panel.setSpacing(10); panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); panel.setSize("300", "100"); panel.add(textBox); panel.add(button); DecoratorPanel decoratorPanel = new DecoratorPanel(); decoratorPanel.add(panel); RootPanel.get("gwtContainer").add(decoratorPanel); } /** * create a custom click handler which will call * onClick method when button is clicked. */ private class MyClickHandler implements ClickHandler { @Override public void onClick(ClickEvent event) { Window.alert("Hello World!"); } } /** * create a custom key down handler which will call * onKeyDown method when a key is down in textbox. */ private class MyKeyDownHandler implements KeyDownHandler { @Override public void onKeyDown(KeyDownEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ Window.alert(((TextBox)event.getSource()).getValue()); } } } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
GWT - Custom Widgets
GWT提供了三種創建自定義用戶界面元素的方法。有三個一般的策略可以遵循;
通過擴展複合類來創建小部件這是創建自定義小部件的最常見和最簡單的方法。在這裡,您可以使用現有的小部件創建具有自定義屬性的複合視圖。
在JAVA中使用GWT DOM API創建小部件,GWT基本小部件就是這樣創建的。創建自定義小部件仍然是一個非常複雜的方法,應該謹慎使用。
使用JavaScript並使用JSNI將其包裝在一個小部件中−這通常只能作爲最後的手段來完成。考慮到本機方法的跨瀏覽器含義,它變得非常複雜,也變得更難調試。
Create Custom Widget with Composite Class
這個例子將帶您通過簡單的步驟來展示在GWT中創建自定義小部件的過程。按照以下步驟更新我們在GWT-Basic Widgets−一章中創建的GWT應用程式;
在這裡,我們將通過擴展Composite類來創建自定義小部件,這是構建自定義小部件的最簡單方法。
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Custom Widget Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; public class HelloWorld implements EntryPoint { /** * A composite of a TextBox and a CheckBox that optionally enables it. */ private static class OptionalTextBox extends Composite implements ClickHandler { private TextBox textBox = new TextBox(); private CheckBox checkBox = new CheckBox(); private boolean enabled = true; public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } /** * Style this widget using .optionalTextWidget CSS class.<br/> * Style textbox using .optionalTextBox CSS class.<br/> * Style checkbox using .optionalCheckBox CSS class.<br/> * Constructs an OptionalTextBox with the given caption * on the check. * @param caption the caption to be displayed with the check box */ public OptionalTextBox(String caption) { // place the check above the text box using a vertical panel. HorizontalPanel panel = new HorizontalPanel(); // panel.setBorderWidth(1); panel.setSpacing(10); panel.add(checkBox); panel.add(textBox); // all composites must call initWidget() in their constructors. initWidget(panel); //set style name for entire widget setStyleName("optionalTextWidget"); //set style name for text box textBox.setStyleName("optionalTextBox"); //set style name for check box checkBox.setStyleName("optionalCheckBox"); textBox.setWidth("200"); // Set the check box's caption, and check it by default. checkBox.setText(caption); checkBox.setValue(enabled); checkBox.addClickHandler(this); enableTextBox(enabled,checkBox.getValue()); } public void onClick(ClickEvent event) { if (event.getSource() == checkBox) { // When the check box is clicked, //update the text box's enabled state. enableTextBox(enabled,checkBox.getValue()); } } private void enableTextBox(boolean enable,boolean isChecked){ enable = (enable && isChecked) || (!enable && !isChecked); textBox.setStyleDependentName("disabled", !enable); textBox.setEnabled(enable); } } public void onModuleLoad() { // Create an optional text box and add it to the root panel. OptionalTextBox otb = new OptionalTextBox( "Want to explain the solution?"); otb.setEnabled(true); RootPanel.get().add(otb); } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
你可以注意到以下幾點
通過擴展複合窗口小部件來創建自定義窗口小部件非常容易。
我們使用GWT內置的widgets、TextBox和CheckBox創建了一個widget,從而使用了可重用的概念。
根據複選框的狀態禁用/啓用文本框。我們提供了一個API來啓用/禁用控制項。
我們已經通過文檔化的CSS樣式公開了內部小部件樣式。
GWT - UiBinder
Introduction
UiBinder是一個框架,用於分離用戶界面的功能和視圖。
UiBinder框架允許開發人員將gwt應用程式構建爲HTML頁面,並在其中配置gwt小部件。
UiBinder框架使得與比Java原始碼更熟悉XML、HTML和CSS的UI設計人員的協作更加容易
UIBinder提供了一種定義用戶界面的聲明方式。
UIBinder將程序邏輯與UI分離。
UIBinder與JSP與servlet類似。
UiBinder Workflow
Step 1 - Create UI Declaration XML File
創建一個基於XML/HTML的用戶界面聲明文件。我們在示例中創建了一個Login.ui.xml文件。
<ui:UiBinder xmlns:ui = 'urn:ui:com.google.gwt.uibinder' xmlns:gwt = 'urn:import:com.google.gwt.user.client.ui' xmlns:res = 'urn:with:com.tutorialspoint.client.LoginResources'> <ui:with type = "com.tutorialspoint.client.LoginResources" field = "res"> </ui:with> <gwt:HTMLPanel> ... </gwt:HTMLPanel> </ui:UiBinder>
Step 2 - Use ui:field for Later Binding
使用XML/HTML元素中的ui:field屬性將XML中的ui欄位與JAVA文件中的ui欄位關聯起來,以便以後綁定。
<gwt:Label ui:field = "completionLabel1" /> <gwt:Label ui:field = "completionLabel2" />
Step 3 - Create Java counterpart of UI XML
通過擴展複合窗口小部件,創建基於Java的XML布局對應項。我們在示例中創建了一個Login.java文件。
package com.tutorialspoint.client; ... public class Login extends Composite { ... }
Step 4 - Bind Java UI fields with UiField annotation
使用Login.java中的@UiField注釋指定對應的類成員以綁定到Login.ui.XML中基於XML的欄位
public class Login extends Composite { ... @UiField Label completionLabel1; @UiField Label completionLabel2; ... }
Step 5 - Bind Java UI with UI XML with UiTemplate annotation
指示GWT使用@UiTemplate注釋綁定基於java的組件Login.java和基於XML的布局Login.ui.XML
public class Login extends Composite { private static LoginUiBinder uiBinder = GWT.create(LoginUiBinder.class); /* * @UiTemplate is not mandatory but allows multiple XML templates * to be used for the same widget. * Default file loaded will be <class-name>.ui.xml */ @UiTemplate("Login.ui.xml") interface LoginUiBinder extends UiBinder<Widget, Login> { } ... }
Step 6 - Create CSS File
創建一個外部CSS文件Login.CSS和基於Java的ResourceLoginResources.Java與CSS樣式等效的文件
.blackText { font-family: Arial, Sans-serif; color: #000000; font-size: 11px; text-align: left; } ...
Step 7 - Create Java based Resource File for CSS File
package com.tutorialspoint.client; ... public interface LoginResources extends ClientBundle { public interface MyCss extends CssResource { String blackText(); ... } @Source("Login.css") MyCss style(); }
Step 8 - Attach CSS resource in Java UI Code file.
使用基於Java的widget類的控制項附加外部CSS文件Login.CSS
public Login() { this.res = GWT.create(LoginResources.class); res.style().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); }
UIBinder Complete Example
這個例子將引導您通過簡單的步驟來展示UIBinder在GWT中的使用。按照以下步驟更新我們在GWT-Create application−一章中創建的GWT應用程式;
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Inherit the UiBinder module. --> <inherits name = "com.google.gwt.uibinder.UiBinder"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path ='client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>UiBinder Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
現在創建一個新的UiBinder模板和所有者類(File→new→UiBinder)。
選擇項目的客戶端包,然後將其命名爲Login。保留所有其他默認值。單擊Finish按鈕,插件將創建一個新的UiBinder模板和所有者類。
.blackText { font-family: Arial, Sans-serif; color: #000000; font-size: 11px; text-align: left; } .redText { font-family: Arial, Sans-serif; color: #ff0000; font-size: 11px; text-align: left; } .loginButton { border: 1px solid #3399DD; color: #FFFFFF; background: #555555; font-size: 11px; font-weight: bold; margin: 0 5px 0 0; padding: 4px 10px 5px; text-shadow: 0 -1px 0 #3399DD; } .box { border: 1px solid #AACCEE; display: block; font-size: 12px; margin: 0 0 5px; padding: 3px; width: 203px; } .background { background-color: #999999; border: 1px none transparent; color: #000000; font-size: 11px; margin-left: -8px; margin-top: 5px; padding: 6px; }
package com.tutorialspoint.client; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; public interface LoginResources extends ClientBundle { /** * Sample CssResource. */ public interface MyCss extends CssResource { String blackText(); String redText(); String loginButton(); String box(); String background(); } @Source("Login.css") MyCss style(); }
<ui:UiBinder xmlns:ui = 'urn:ui:com.google.gwt.uibinder' xmlns:gwt = 'urn:import:com.google.gwt.user.client.ui' xmlns:res = 'urn:with:com.tutorialspoint.client.LoginResources'> <ui:with type = "com.tutorialspoint.client.LoginResources" field = "res"> </ui:with> <gwt:HTMLPanel> <div align = "center"> <gwt:VerticalPanel res:styleName = "style.background"> <gwt:Label text = "Login" res:styleName = "style.blackText" /> <gwt:TextBox ui:field="loginBox" res:styleName = "style.box" /> <gwt:Label text = "Password" res:styleName = "style.blackText" /> <gwt:PasswordTextBox ui:field = "passwordBox" res:styleName = "style.box" /> <gwt:HorizontalPanel verticalAlignment = "middle"> <gwt:Button ui:field = "buttonSubmit" text="Submit" res:styleName = "style.loginButton" /> <gwt:CheckBox ui:field = "myCheckBox" /> <gwt:Label ui:field = "myLabel" text = "Remember me" res:styleName = "style.blackText" /> </gwt:HorizontalPanel> <gwt:Label ui:field = "completionLabel1" res:styleName = "style.blackText" /> <gwt:Label ui:field = "completionLabel2" res:styleName = "style.blackText" /> </gwt:VerticalPanel> </div> </gwt:HTMLPanel> </ui:UiBinder>
package com.tutorialspoint.client; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.uibinder.client.UiTemplate; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; public class Login extends Composite { private static LoginUiBinder uiBinder = GWT.create(LoginUiBinder.class); /* * @UiTemplate is not mandatory but allows multiple XML templates * to be used for the same widget. * Default file loaded will be <class-name>.ui.xml */ @UiTemplate("Login.ui.xml") interface LoginUiBinder extends UiBinder<Widget, Login> { } @UiField(provided = true) final LoginResources res; public Login() { this.res = GWT.create(LoginResources.class); res.style().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); } @UiField TextBox loginBox; @UiField TextBox passwordBox; @UiField Label completionLabel1; @UiField Label completionLabel2; private Boolean tooShort = false; /* * Method name is not relevant, the binding is done according to the class * of the parameter. */ @UiHandler("buttonSubmit") void doClickSubmit(ClickEvent event) { if (!tooShort) { Window.alert("Login Successful!"); } else { Window.alert("Login or Password is too short!"); } } @UiHandler("loginBox") void handleLoginChange(ValueChangeEvent<String> event) { if (event.getValue().length() < 6) { completionLabel1.setText("Login too short (Size must be > 6)"); tooShort = true; } else { tooShort = false; completionLabel1.setText(""); } } @UiHandler("passwordBox") void handlePasswordChange(ValueChangeEvent<String> event) { if (event.getValue().length() < 6) { tooShort = true; completionLabel2.setText("Password too short (Size must be > 6)"); } else { tooShort = false; completionLabel2.setText(""); } } }
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.RootPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { RootPanel.get().add(new Login()); } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
GWT - RPC Communication
基於GWT的應用程式通常由客戶端模塊和伺服器端模塊組成。客戶端代碼在瀏覽器中運行,伺服器端代碼在web伺服器中運行。客戶端代碼必須通過網絡發出HTTP請求才能訪問伺服器端數據。
遠程過程調用(RPC,Remote Procedure Call)是GWT使用的一種機制,其中客戶端代碼可以直接執行伺服器端方法。
GWT-RPC是基於servlet的。
GWT-RPC是異步的,客戶機在通信期間從不被阻塞。
使用GWT RPC Java對象可以直接在客戶機和伺服器之間發送(由GWT框架自動序列化)。
伺服器端servlet被稱爲服務。
從客戶端代碼調用伺服器端servlet方法的遠程過程調用稱爲調用服務。
GWT RPC Components
以下是GWT-RPC通信機制中使用的三個組件
- A remote service (server-side servlet) that runs on the server.
- Client code to invoke that service.
- Java data objects which will be passed between client and server.
GWT client and server both serialize and deserialize data automatically so developers are 不需要的 to serialize/deserialize objects and data objects can travel over HTTP.
下圖顯示了RPC體系結構。
要開始使用RPC,我們需要遵循GWT約定。
RPC Communication Workflow
Step 1 - Create a Serializable Model Class
在客戶端定義一個java模型對象,該對象應該是可序列化的。
public class Message implements Serializable { ... private String message; public Message(){}; public void setMessage(String message) { this.message = message; } ... }
Step 2 - Create a Service Interface
在客戶端爲服務定義一個接口,該接口擴展列出所有服務方法的RemoteService。
使用annotation@remoteservicererelativepath將服務映射爲遠程servlet相對於模塊基URL的默認路徑。
@RemoteServiceRelativePath("message") public interface MessageService extends RemoteService { Message getMessage(String input); }
Step 3 - Create a Async Service Interface
在客戶機端(與上面提到的服務位於同一位置)定義一個異步服務接口,該接口將在GWT客戶機代碼中使用。
public interface MessageServiceAsync { void getMessage(String input, AsyncCallback<Message> callback); }
Step 4 - Create a Service Implementation Servlet class
在伺服器端實現接口,該類應擴展RemoteServiceServlet類。
public class MessageServiceImpl extends RemoteServiceServlet implements MessageService{ ... public Message getMessage(String input) { String messageString = "Hello " + input + "!"; Message message = new Message(); message.setMessage(messageString); return message; } }
Step 5 - Update Web.xml to include Servlet declaration
編輯web應用程式部署描述符(web.xml)以包含MessageServiceImpl Servlet聲明。
<web-app> ... <servlet> <servlet-name>messageServiceImpl</servlet-name> <servlet-class>com.tutorialspoint.server.MessageServiceImpl </servlet-class> </servlet> <servlet-mapping> <servlet-name>messageServiceImpl</servlet-name> <url-pattern>/helloworld/message</url-pattern> </servlet-mapping> </web-app>
Step 6 - Make the remote procedure call in Application Code
創建服務代理類。
MessageServiceAsync messageService = GWT.create(MessageService.class);
創建AsyncCallback處理程序以處理伺服器將消息返回給客戶端的RPC回調
class MessageCallBack implements AsyncCallback<Message> { @Override public void onFailure(Throwable caught) { Window.alert("Unable to obtain server response: " + caught.getMessage()); } @Override public void onSuccess(Message result) { Window.alert(result.getMessage()); } }
當用戶與UI交互時調用遠程服務
public class HelloWorld implements EntryPoint { ... public void onModuleLoad() { ... buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { messageService.getMessage(txtName.getValue(), new MessageCallBack()); } }); ... } }
RPC Communication Complete Example
這個例子將帶您通過簡單的步驟來展示GWT中RPC通信的例子。按照以下步驟更新我們在GWT-Create application−一章中創建的GWT應用程式;
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Inherit the UiBinder module. --> <inherits name = "com.google.gwt.uibinder.UiBinder"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>RPC Communication Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import java.io.Serializable; public class Message implements Serializable { private static final long serialVersionUID = 1L; private String message; public Message(){}; public void setMessage(String message) { this.message = message; } public String getMessage() { return message; } }
package com.tutorialspoint.client; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("message") public interface MessageService extends RemoteService { Message getMessage(String input); }
package com.tutorialspoint.client; import com.google.gwt.user.client.rpc.AsyncCallback; public interface MessageServiceAsync { void getMessage(String input, AsyncCallback<Message> callback); }
package com.tutorialspoint.server; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.tutorialspoint.client.Message; import com.tutorialspoint.client.MessageService; public class MessageServiceImpl extends RemoteServiceServlet implements MessageService{ private static final long serialVersionUID = 1L; public Message getMessage(String input) { String messageString = "Hello " + input + "!"; Message message = new Message(); message.setMessage(messageString); return message; } }
更新修改後的web應用程式部署描述符的內容,使其包含MessageServiceImpl Servlet聲明。
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <!-- Default page to serve --> <welcome-file-list> <welcome-file>HelloWorld.html</welcome-file> </welcome-file-list> <servlet> <servlet-name>messageServiceImpl</servlet-name> <servlet-class>com.tutorialspoint.server.MessageServiceImpl </servlet-class> </servlet> <servlet-mapping> <servlet-name>messageServiceImpl</servlet-name> <url-pattern>/helloworld/message</url-pattern> </servlet-mapping> </web-app>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { private MessageServiceAsync messageService = GWT.create(MessageService.class); private class MessageCallBack implements AsyncCallback<Message> { @Override public void onFailure(Throwable caught) { /* server side error occured */ Window.alert("Unable to obtain server response: " + caught.getMessage()); } @Override public void onSuccess(Message result) { /* server returned result, show user the message */ Window.alert(result.getMessage()); } } public void onModuleLoad() { /*create UI */ final TextBox txtName = new TextBox(); txtName.setWidth("200"); txtName.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ /* make remote call to server to get the message */ messageService.getMessage(txtName.getValue(), new MessageCallBack()); } } }); Label lblName = new Label("Enter your name: "); Button buttonMessage = new Button("Click Me!"); buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { /* make remote call to server to get the message */ messageService.getMessage(txtName.getValue(), new MessageCallBack()); } }); HorizontalPanel hPanel = new HorizontalPanel(); hPanel.add(lblName); hPanel.add(txtName); hPanel.setCellWidth(lblName, "130"); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(hPanel); vPanel.add(buttonMessage); vPanel.setCellHorizontalAlignment(buttonMessage, HasHorizontalAlignment.ALIGN_RIGHT); DecoratorPanel panel = new DecoratorPanel(); panel.add(vPanel); // Add widgets to the root panel. RootPanel.get("gwtContainer").add(panel); } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
GWT - JUnit Integration
GWT使用JUnit測試框架爲客戶端代碼的自動測試提供execellent支持。在本文中,我們將演示GWT和JUNIT集成。
Download Junit archive
JUnit官方網站
下載Junit-4.10.jar
OS | Archive name |
---|---|
Windows | junit4.10.jar |
Linux | junit4.10.jar |
Mac | junit4.10.jar |
將下載的jar文件存儲到計算機上的某個位置。我們已將其存儲在C:/>JUNIT
Locate GWT installation folder
OS | GWT installation folder |
---|---|
Windows | C:\GWT\gwt-2.1.0 |
Linux | /usr/local/GWT/gwt-2.1.0 |
Mac | /Library/GWT/gwt-2.1.0 |
GWTTestCase Class
GWT提供了提供JUnit集成的基類。在JUnit下運行一個擴展GWTTestCase的編譯類將啓動HtmlUnit瀏覽器,該瀏覽器用於模擬測試執行期間的應用程式行爲。
GWTTestCase是從JUnit的TestCase派生的類,可以使用JUnit TestRunner運行它。
Using webAppCreator
GWT提供了一個特殊的命令行工具webAppCreator,它可以爲我們生成一個starter測試用例,以及ant目標和eclipse啓動配置,以便在開發模式和生產模式下進行測試。
打開命令提示符並轉到要在其中創建具有測試支持的新項目的C:\>GWT_WORKSPACE>。運行以下命令
C:\GWT_WORKSPACE>C:\GWT\gwt-2.1.0\webAppCreator -out HelloWorld -junit C:\JUNIT\junit-4.10.jar com.tutorialspoint.HelloWorld
值得注意的一點
- We are executing webAppCreator command line utility.
- HelloWorld is the name of the project to be created
- -junit option instructs webAppCreator to add junit suppport to project
- com.tutorialspoint.HelloWorld is the name of the module
驗證輸出。
Created directory HelloWorld\src Created directory HelloWorld\war Created directory HelloWorld\war\WEB-INF Created directory HelloWorld\war\WEB-INF\lib Created directory HelloWorld\src\com\tutorialspoint Created directory HelloWorld\src\com\tutorialspoint\client Created directory HelloWorld\src\com\tutorialspoint\server Created directory HelloWorld\src\com\tutorialspoint\shared Created directory HelloWorld\test\com\tutorialspoint Created directory HelloWorld\test\com\tutorialspoint\client Created file HelloWorld\src\com\tutorialspoint\HelloWorld.gwt.xml Created file HelloWorld\war\HelloWorld.html Created file HelloWorld\war\HelloWorld.css Created file HelloWorld\war\WEB-INF\web.xml Created file HelloWorld\src\com\tutorialspoint\client\HelloWorld.java Created file HelloWorld\src\com\tutorialspoint\client\GreetingService.java Created file HelloWorld\src\com\tutorialspoint\client\GreetingServiceAsync.java Created file HelloWorld\src\com\tutorialspoint\server\GreetingServiceImpl.java Created file HelloWorld\src\com\tutorialspoint\shared\FieldVerifier.java Created file HelloWorld\build.xml Created file HelloWorld\README.txt Created file HelloWorld\test\com\tutorialspoint\HelloWorldJUnit.gwt.xml Created file HelloWorld\test\com\tutorialspoint\client\HelloWorldTest.java Created file HelloWorld\.project Created file HelloWorld\.classpath Created file HelloWorld\HelloWorld.launch Created file HelloWorld\HelloWorldTest-dev.launch Created file HelloWorld\HelloWorldTest-prod.launch
Understanding the test class: HelloWorldTest.java
package com.tutorialspoint.client; import com.tutorialspoint.shared.FieldVerifier; import com.google.gwt.core.client.GWT; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; /** * GWT JUnit tests must extend GWTTestCase. */ public class HelloWorldTest extends GWTTestCase { /** * must refer to a valid module that sources this class. */ public String getModuleName() { return "com.tutorialspoint.HelloWorldJUnit"; } /** * tests the FieldVerifier. */ public void testFieldVerifier() { assertFalse(FieldVerifier.isValidName(null)); assertFalse(FieldVerifier.isValidName("")); assertFalse(FieldVerifier.isValidName("a")); assertFalse(FieldVerifier.isValidName("ab")); assertFalse(FieldVerifier.isValidName("abc")); assertTrue(FieldVerifier.isValidName("abcd")); } /** * this test will send a request to the server using the greetServer * method in GreetingService and verify the response. */ public void testGreetingService() { /* create the service that we will test. */ GreetingServiceAsync greetingService = GWT.create(GreetingService.class); ServiceDefTarget target = (ServiceDefTarget) greetingService; target.setServiceEntryPoint(GWT.getModuleBaseURL() + "helloworld/greet"); /* since RPC calls are asynchronous, we will need to wait for a response after this test method returns. This line tells the test runner to wait up to 10 seconds before timing out. */ delayTestFinish(10000); /* send a request to the server. */ greetingService.greetServer("GWT User", new AsyncCallback<String>() { public void onFailure(Throwable caught) { /* The request resulted in an unexpected error. */ fail("Request failure: " + caught.getMessage()); } public void onSuccess(String result) { /* verify that the response is correct. */ assertTrue(result.startsWith("Hello, GWT User!")); /* now that we have received a response, we need to tell the test runner that the test is complete. You must call finishTest() after an asynchronous test finishes successfully, or the test will time out.*/ finishTest(); } }); } }
值得注意的一點
Sr.No. | Note |
---|---|
1 | HelloWorldTest class was generated in the com.tutorialspoint.client package under the HelloWorld/test directory. |
2 | HelloWorldTest class will contain unit test cases for HelloWorld. |
3 | HelloWorldTest class extends the GWTTestCase class in the com.google.gwt.junit.client package. |
4 | HelloWorldTest class has an abstract method (getModuleName) that must return the name of the GWT module. For HelloWorld, this is com.tutorialspoint.HelloWorldJUnit. |
5 | HelloWorldTest class is generated with two sample test cases testFieldVerifier, testSimple. We've added testGreetingService. |
6 | These methods use one of the many assert* functions that it inherits from the JUnit Assert class, which is an ancestor of GWTTestCase. |
7 | The assertTrue(boolean) function asserts that the boolean argument passed in evaluates to true. If not, the test will fail when run in JUnit. |
GWT - JUnit Integration Complete Example
這個例子將帶您通過簡單的步驟來展示GWT中JUnit集成的例子。
按照以下步驟更新我們在上面創建的GWT應用程式−
Step | Description |
---|---|
1 | Import the project with a name HelloWorld in eclipse using import existing project wizard (File → Import → General → Existing Projects into workspace). |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是eclipse中的項目結構。
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Inherit the UiBinder module. --> <inherits name = "com.google.gwt.uibinder.UiBinder"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>JUnit Integration Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { /*create UI */ final TextBox txtName = new TextBox(); txtName.setWidth("200"); txtName.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ Window.alert(getGreeting(txtName.getValue())); } } }); Label lblName = new Label("Enter your name: "); Button buttonMessage = new Button("Click Me!"); buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { Window.alert(getGreeting(txtName.getValue())); } }); HorizontalPanel hPanel = new HorizontalPanel(); hPanel.add(lblName); hPanel.add(txtName); hPanel.setCellWidth(lblName, "130"); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(hPanel); vPanel.add(buttonMessage); vPanel.setCellHorizontalAlignment(buttonMessage, HasHorizontalAlignment.ALIGN_RIGHT); DecoratorPanel panel = new DecoratorPanel(); panel.add(vPanel); // Add widgets to the root panel. RootPanel.get("gwtContainer").add(panel); } public String getGreeting(String name){ return "Hello "+name+"!"; } }
package com.tutorialspoint.client; import com.tutorialspoint.shared.FieldVerifier; import com.google.gwt.core.client.GWT; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; /** * GWT JUnit tests must extend GWTTestCase. */ public class HelloWorldTest extends GWTTestCase { /** * must refer to a valid module that sources this class. */ public String getModuleName() { return "com.tutorialspoint.HelloWorldJUnit"; } /** * tests the FieldVerifier. */ public void testFieldVerifier() { assertFalse(FieldVerifier.isValidName(null)); assertFalse(FieldVerifier.isValidName("")); assertFalse(FieldVerifier.isValidName("a")); assertFalse(FieldVerifier.isValidName("ab")); assertFalse(FieldVerifier.isValidName("abc")); assertTrue(FieldVerifier.isValidName("abcd")); } /** * this test will send a request to the server using the greetServer * method in GreetingService and verify the response. */ public void testGreetingService() { /* create the service that we will test. */ GreetingServiceAsync greetingService = GWT.create(GreetingService.class); ServiceDefTarget target = (ServiceDefTarget) greetingService; target.setServiceEntryPoint(GWT.getModuleBaseURL() + "helloworld/greet"); /* since RPC calls are asynchronous, we will need to wait for a response after this test method returns. This line tells the test runner to wait up to 10 seconds before timing out. */ delayTestFinish(10000); /* send a request to the server. */ greetingService.greetServer("GWT User", new AsyncCallback<String>() { public void onFailure(Throwable caught) { /* The request resulted in an unexpected error. */ fail("Request failure: " + caught.getMessage()); } public void onSuccess(String result) { /* verify that the response is correct. */ assertTrue(result.startsWith("Hello, GWT User!")); /* now that we have received a response, we need to tell the test runner that the test is complete. You must call finishTest() after an asynchronous test finishes successfully, or the test will time out.*/ finishTest(); } }); /** * tests the getGreeting method. */ public void testGetGreeting() { HelloWorld helloWorld = new HelloWorld(); String name = "Robert"; String expectedGreeting = "Hello "+name+"!"; assertEquals(expectedGreeting,helloWorld.getGreeting(name)); } } }
Run test cases in Eclipse using generated launch configurations
我們將使用webAppCreator爲開發模式和生產模式生成的啓動配置在Eclipse中運行單元測試。
Run the JUnit test in development mode
- From the Eclipse menu bar, select Run → Run Configurations...
- Under JUnit section, select HelloWorldTest-dev
- To save the changes to the Arguments, press Apply
- To run the test, press Run
如果你的申請一切順利,這將產生以下結果;
Run the JUnit test in production mode
- From the Eclipse menu bar, select Run → Run Configurations...
- Under JUnit section, select HelloWorldTest-prod
- To save the changes to the Arguments, press Apply
- To run the test, press Run
如果你的申請一切順利,這將產生以下結果;
GWT - Debugging Application
GWT提供了調試客戶端和伺服器端代碼的可執行性。
在開發模式中,GWT應用程式是基於Java代碼的,不會轉換爲JavaScript。
當應用程式以開發模式運行時,Java虛擬機(JVM)實際上是以編譯後的Java字節碼執行應用程式代碼,使用GWT功能連接到瀏覽器窗口。
GWT使用基於瀏覽器的插件連接到JVM。
因此開發人員可以使用任何基於Java的IDE來調試客戶端GWT代碼和伺服器端代碼。
在本文中,我們將演示如何使用Eclipse調試GWT客戶機代碼。我們將完成以下任務;
- Set break points in the code and see them in BreakPoint Explorer.
- Step through the code line by line during debugging.
- View the values of variable.
- Inspect the values of all the variables.
- Inspect the value of an expression.
- Display the stack frame for suspended threads.
Debugging Example
本例將帶您通過簡單的步驟演示如何調試GWT應用程式。按照以下步驟更新我們在GWT-Create application−一章中創建的GWT應用程式;
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; } .gwt-Label{ font-size: 150%; font-weight: bold; color:red; padding:5px; margin:5px; }
下面是修改後的HTML宿主文件的內容,可以容納兩個按鈕。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1>Debugging Application Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { public void onModuleLoad() { /*create UI */ final TextBox txtName = new TextBox(); txtName.setWidth("200"); txtName.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ Window.alert(getGreeting(txtName.getValue())); } } }); Label lblName = new Label("Enter your name: "); Button buttonMessage = new Button("Click Me!"); buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { Window.alert(getGreeting(txtName.getValue())); }}); HorizontalPanel hPanel = new HorizontalPanel(); hPanel.add(lblName); hPanel.add(txtName); hPanel.setCellWidth(lblName, "130"); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(hPanel); vPanel.add(buttonMessage); vPanel.setCellHorizontalAlignment(buttonMessage, HasHorizontalAlignment.ALIGN_RIGHT); DecoratorPanel panel = new DecoratorPanel(); panel.add(vPanel); // Add widgets to the root panel. RootPanel.get("gwtContainer").add(panel); } public String getGreeting(String name){ return "Hello "+name+"!"; } }
Step 1 - Place BreakPoints
在HelloWorld.java的onModuleLoad()的第一行放置斷點
Step 2 - Debug Application
現在點擊debug application菜單並選擇application來調試應用程式。
如果一切正常,您必須看到GWT開發模式在Eclipse中處於活動狀態,其中包含如下所示的URL。雙擊URL以打開GWT應用程式。
一旦應用程式啓動,當我們將斷點放在入口點方法的第一行時,您將看到重點放在Eclipse斷點上。
您可以看到掛起線程的stacktrace。
可以看到表達式的值。
您可以看到放置的斷點列表。
現在繼續按F6,直到到達onModuleLoad()方法的最後一行。作爲功能鍵的參考,F6逐行檢查代碼,F5步驟進一步深入,F8將繼續應用。現在您可以看到onModuleLoad()方法的所有變量的值列表。
GWT客戶機代碼的調試方式與Java應用程式的調試方式相同。將斷點放置到任意行,並使用GWT的調試功能。
GWT - Internationalization
GWT提供了三種國際化GWT應用程式的方法,我們將演示靜態字符串國際化在項目中最常用的用法。
Sr.No. | Technique & Description |
---|---|
1 |
靜態字符串國際化 這種技術是最流行的,運行時只需要很少的開銷;是轉換常量和參數化字符串的非常有效的技術;實現起來最簡單。 靜態字符串國際化使用標準Java屬性文件來存儲轉換的字符串和參數化消息,並創建強類型Java接口來檢索它們的值。 |
2 |
動態字符串國際化 This technique is very flexible but slower than static string internationalization. Host page contains the localized strings therefore, applications are 不需要的 to be recompiled when we add a new locale. If GWT application is to be integrated with an existing server-side localization system, then this technique is to be used. |
3 |
可定位接口(b) 這項技術是三項技術中最強大的。實現本地化允許我們創建自定義類型的本地化版本。這是一種先進的國際化技術。 |
Workflow of Internationalizing a GWT Application
Step 1 - Create properties files
創建包含要在應用程式中使用的消息的屬性文件。我們在示例中創建了一個HelloWorldMessages.properties文件。
enterName = Enter your name clickMe = Click Me applicationTitle = Application Internationalization Demonstration greeting = Hello {0}
創建包含特定於區域設置的翻譯值的屬性文件。我們在示例中創建了一個HelloWorldMessages\u de.properties文件。此文件包含德語翻譯。_de指定德語區域設置,我們將在應用程式中支持德語。
如果要使用Eclipse創建屬性文件,請將該文件的編碼更改爲UTF-8。選擇該文件,然後右鍵單擊該文件以打開其屬性窗口。選擇文本文件編碼爲其他UTF-8。應用並保存更改。
enterName = Geben Sie Ihren Namen clickMe = Klick mich applicationTitle = Anwendung Internationalisierung Demonstration greeting = Hallo {0}
Step 2 - Add i18n module to Module Descriptor XML File
更新模塊文件HelloWorld.gwt.xml以包括對德語語言環境的支持
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> ... <extend-property name = "locale" values="de" /> ... </module>
Step 3 - Create Interface equivalent to properties file
通過擴展GWT的消息接口以包括對內部化的支持,創建HelloWorldMessages.java接口。它應該包含與屬性文件中的鍵相同的方法名。占位符將替換爲字符串參數。
public interface HelloWorldMessages extends Messages { @DefaultMessage("Enter your name") String enterName(); @DefaultMessage("Click Me") String clickMe(); @DefaultMessage("Application Internalization Demonstration") String applicationTitle(); @DefaultMessage("Hello {0}") String greeting(String name); }
Step 4 - Use Message Interface in UI component.
使用HelloWorld中的HelloWorld messages對象獲取消息。
public class HelloWorld implements EntryPoint { /* create an object of HelloWorldMessages interface using GWT.create() method */ private HelloWorldMessages messages = GWT.create(HelloWorldMessages.class); public void onModuleLoad() { ... Label titleLabel = new Label(messages.applicationTitle()); //Add title to the application RootPanel.get("gwtAppTitle").add(titleLabel); ... } }
Internationalization - Complete Example
這個例子將引導您通過簡單的步驟來演示GWT應用程式的國際化能力。
按照以下步驟更新我們在GWT-Create application−一章中創建的GWT應用程式;
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <extend-property name = "locale" values="de" /> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容。
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <h1 id = "gwtAppTitle"></h1> <div id = "gwtContainer"></div> </body> </html>
enterName = Enter your name clickMe = Click Me applicationTitle = Application Internationalization Demonstration greeting = Hello {0}
enterName = Geben Sie Ihren Namen clickMe = Klick mich applicationTitle = Anwendung Internationalisierung Demonstration greeting = Hallo {0}
package com.tutorialspoint.client; import com.google.gwt.i18n.client.Messages; public interface HelloWorldMessages extends Messages { @DefaultMessage("Enter your name") String enterName(); @DefaultMessage("Click Me") String clickMe(); @DefaultMessage("Application Internationalization Demonstration") String applicationTitle(); @DefaultMessage("Hello {0}") String greeting(String name); }
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { /* create an object of HelloWorldMessages interface using GWT.create() method */ private HelloWorldMessages messages = GWT.create(HelloWorldMessages.class); public void onModuleLoad() { /*create UI */ final TextBox txtName = new TextBox(); txtName.setWidth("200"); txtName.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ Window.alert(getGreeting(txtName.getValue())); } } }); Label lblName = new Label(messages.enterName() + ": "); Button buttonMessage = new Button(messages.clickMe() + "!"); buttonMessage.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { Window.alert(getGreeting(txtName.getValue())); } }); HorizontalPanel hPanel = new HorizontalPanel(); hPanel.add(lblName); hPanel.add(txtName); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(hPanel); vPanel.add(buttonMessage); vPanel.setCellHorizontalAlignment(buttonMessage, HasHorizontalAlignment.ALIGN_RIGHT); DecoratorPanel panel = new DecoratorPanel(); panel.add(vPanel); Label titleLabel = new Label(messages.applicationTitle()); //Add title to the application RootPanel.get("gwtAppTitle").add(titleLabel); // Add widgets to the root panel. RootPanel.get("gwtContainer").add(panel); } public String getGreeting(String name){ return messages.greeting(name + "!"); } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
Now update the URL to contain the locale=de.Set URL − http://127.0.0.1:8888/HelloWorld.html?gwt.codesvr=127.0.0.1:9997&locale=de. 如果你的申請一切順利,這將產生以下結果;
GWT - History Class
GWT應用程式通常是運行JavaScripts的單頁應用程式,不包含很多頁面,因此瀏覽器不會跟蹤用戶與應用程式的交互。若要使用瀏覽器的歷史記錄功能,應用程式應爲每個可導航頁面生成唯一的URL片段。
GWT提供歷史機制來處理這種情況。
GWT使用一個術語token這只是一個字符串,應用程式可以解析它以返回特定的狀態。應用程式將在瀏覽器的歷史記錄中將此令牌保存爲URL片段。
例如,一個名爲「pagindex1」的歷史標記將被添加到URL中,如下所示−
http://www.tutorialspoint.com/HelloWorld.html#pageIndex0
History Management Workflow
Step 1 - Enable History support
爲了使用GWT歷史支持,我們必須首先在宿主HTML頁面中嵌入以下iframe。
<iframe src = "javascript:''" id = "__gwt_historyFrame" style = "width:0;height:0;border:0"></iframe>
Step 2 - Add token to History
下面的示例統計了如何將令牌添加到瀏覽器歷史記錄中
int index = 0; History.newItem("pageIndex" + index);
Step 3 - Retrive token from History
當用戶使用瀏覽器的後退/前進按鈕時,我們將檢索令牌並相應地更新我們的應用程式狀態。
History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { String historyToken = event.getValue(); /* parse the history token */ try { if (historyToken.substring(0, 9).equals("pageIndex")) { String tabIndexToken = historyToken.substring(9, 10); int tabIndex = Integer.parseInt(tabIndexToken); /* select the specified tab panel */ tabPanel.selectTab(tabIndex); } else { tabPanel.selectTab(0); } } catch (IndexOutOfBoundsException e) { tabPanel.selectTab(0); } } });
現在讓我們看看歷史課的實際情況。
History Class - Complete Example
This example will take you through simple steps to demonstrate History Management of a GWT application. 按照以下步驟更新我們在GWT-Create application−一章中創建的GWT應用程式;
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <iframe src = "javascript:''"id = "__gwt_historyFrame" style = "width:0;height:0;border:0"></iframe> <h1> History Class Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TabPanel; public class HelloWorld implements EntryPoint { /** * This is the entry point method. */ public void onModuleLoad() { /* create a tab panel to carry multiple pages */ final TabPanel tabPanel = new TabPanel(); /* create pages */ HTML firstPage = new HTML("<h1>We are on first Page.</h1>"); HTML secondPage = new HTML("<h1>We are on second Page.</h1>"); HTML thirdPage = new HTML("<h1>We are on third Page.</h1>"); String firstPageTitle = "First Page"; String secondPageTitle = "Second Page"; String thirdPageTitle = "Third Page"; tabPanel.setWidth("400"); /* add pages to tabPanel*/ tabPanel.add(firstPage, firstPageTitle); tabPanel.add(secondPage,secondPageTitle); tabPanel.add(thirdPage, thirdPageTitle); /* add tab selection handler */ tabPanel.addSelectionHandler(new SelectionHandler<Integer>() { @Override public void onSelection(SelectionEvent<Integer> event) { /* add a token to history containing pageIndex History class will change the URL of application by appending the token to it. */ History.newItem("pageIndex" + event.getSelectedItem()); } }); /* add value change handler to History this method will be called, when browser's Back button or Forward button are clicked and URL of application changes. */ History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { String historyToken = event.getValue(); /* parse the history token */ try { if (historyToken.substring(0, 9).equals("pageIndex")) { String tabIndexToken = historyToken.substring(9, 10); int tabIndex = Integer.parseInt(tabIndexToken); /* select the specified tab panel */ tabPanel.selectTab(tabIndex); } else { tabPanel.selectTab(0); } } catch (IndexOutOfBoundsException e) { tabPanel.selectTab(0); } } }); /* select the first tab by default */ tabPanel.selectTab(0); /* add controls to RootPanel */ RootPanel.get().add(tabPanel); } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
現在單擊每個選項卡以選擇不同的頁面。
您應該注意,當選擇每個選項卡時,應用程式url會更改,並且會將pageIndex添加到url中。
您還可以看到瀏覽器的後退和前進按鈕現在已啓用。
使用瀏覽器的後退和前進按鈕,您將看到相應地選擇了不同的選項卡。
GWT - Bookmark Support
GWT使用一個歷史類來支持瀏覽器歷史管理,您可以參考GWT-history class一章。
GWT使用一個術語token這只是一個字符串,應用程式可以解析它以返回特定的狀態。應用程式將在瀏覽器的歷史記錄中將此令牌保存爲URL片段。
在GWT-History類中,我們通過編寫代碼來處理歷史中的令牌創建和設置。
在本文中,我們將討論一個特殊的widget超連結,它爲我們自動進行令牌創建和歷史管理,並提供書籤的應用功能。
Bookmarking Example
這個例子將帶您通過簡單的步驟來演示GWT應用程式的書籤。
以下步驟更新我們在GWT-Create applicationchapter−中創建的GWT應用程式;
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <iframe src = "javascript:''"id = "__gwt_historyFrame" style = "width:0;height:0;border:0"></iframe> <h1> Bookmarking Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Hyperlink; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { private TabPanel tabPanel; private void selectTab(String historyToken){ /* parse the history token */ try { if (historyToken.substring(0, 9).equals("pageIndex")) { String tabIndexToken = historyToken.substring(9, 10); int tabIndex = Integer.parseInt(tabIndexToken); /* Select the specified tab panel */ tabPanel.selectTab(tabIndex); } else { tabPanel.selectTab(0); } } catch (IndexOutOfBoundsException e) { tabPanel.selectTab(0); } } /** * This is the entry point method. */ public void onModuleLoad() { /* create a tab panel to carry multiple pages */ tabPanel = new TabPanel(); /* create pages */ HTML firstPage = new HTML("<h1>We are on first Page.</h1>"); HTML secondPage = new HTML("<h1>We are on second Page.</h1>"); HTML thirdPage = new HTML("<h1>We are on third Page.</h1>"); String firstPageTitle = "First Page"; String secondPageTitle = "Second Page"; String thirdPageTitle = "Third Page"; Hyperlink firstPageLink = new Hyperlink("1", "pageIndex0"); Hyperlink secondPageLink = new Hyperlink("2", "pageIndex1"); Hyperlink thirdPageLink = new Hyperlink("3", "pageIndex2"); HorizontalPanel linksHPanel = new HorizontalPanel(); linksHPanel.setSpacing(10); linksHPanel.add(firstPageLink); linksHPanel.add(secondPageLink); linksHPanel.add(thirdPageLink); /* If the application starts with no history token, redirect to a pageIndex0 */ String initToken = History.getToken(); if (initToken.length() == 0) { History.newItem("pageIndex0"); initToken = "pageIndex0"; } tabPanel.setWidth("400"); /* add pages to tabPanel*/ tabPanel.add(firstPage, firstPageTitle); tabPanel.add(secondPage,secondPageTitle); tabPanel.add(thirdPage, thirdPageTitle); /* add value change handler to History * this method will be called, when browser's Back button * or Forward button are clicked. * and URL of application changes. * */ History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { selectTab(event.getValue()); } }); selectTab(initToken); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(tabPanel); vPanel.add(linksHPanel); /* add controls to RootPanel */ RootPanel.get().add(vPanel); } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
現在單擊1、2或3。您可以注意到選項卡隨索引而變化。
您應該注意,當您單擊1、2或3時,應用程式的url將被更改,並將pageIndex添加到url中
您還可以看到瀏覽器的後退和前進按鈕現在已啓用。
使用瀏覽器的後退和前進按鈕,您將看到相應地選擇了不同的選項卡。
右鍵單擊1、2或3。您可以看到諸如「打開」、「在新窗口中打開」、「在新選項卡中打開」、「添加到收藏夾」等選項。
右鍵單擊3。選擇「添加到收藏夾」。將書籤另存爲第3頁。
打開收藏夾並選擇第3頁。您將看到第三個選項卡被選中。
GWT - Logging Framework
日誌框架模擬java.util.logging,因此它使用與伺服器端日誌代碼相同的語法和行爲
GWT日誌記錄是使用.GWT.xml文件配置的。
我們可以將日誌記錄配置爲啓用/禁用;我們可以啓用/禁用特定處理程序,並更改默認日誌記錄級別。
Types of Logger
記錄器以樹結構組織,根記錄器位於樹的根。
記錄器的名稱使用分隔名稱的各個部分來確定父/子關係。
例如,如果我們有兩個loggers Hospital.room1和Hospital.room2,則它們是兄弟姐妹,其父母是名爲Hospital的logger。醫院記錄器(以及名稱不包含點「.」的任何記錄器)將根記錄器作爲父級。
private static Logger room1Logger = Logger.getLogger("Hospital.room1"); private static Logger room2Logger = Logger.getLogger("Hospital.room2"); private static Logger hospitalLogger = Logger.getLogger("Hospital"); private static Logger rootLogger = Logger.getLogger("");
Log Handlers
GWT提供了默認的處理程序,它將顯示使用記錄器創建的日誌條目。
Handler | Logs to | Description |
---|---|---|
SystemLogHandler | stdout | These messages can only be seen in Development Mode in the DevMode window. |
DevelopmentModeLogHandler | DevMode Window | Logs by calling method GWT.log. These messages can only be seen in Development Mode in the DevMode window. |
ConsoleLogHandler | javascript console | Logs to the javascript console, which is used by Firebug Lite (for IE), Safari and Chrome. |
FirebugLogHandler | Firebug | Logs to the firebug console. |
PopupLogHandler | popup | Logs to the popup which resides in the upper left hand corner of application when this handler is enabled. |
SimpleRemoteLogHandler | server | This handler sends log messages to the server, where they will be logged using the server side logging mechanism. |
Configure Logging in GWT Application
要配置HelloWorld.gwt.xml文件以啓用gwt日誌記錄,如下所示−
# add logging module <inherits name = "com.google.gwt.logging.Logging"/> # To change the default logLevel <set-property name = "gwt.logging.logLevel" value = "SEVERE"/> # To enable logging <set-property name = "gwt.logging.enabled" value = "TRUE"/> # To disable a popup Handler <set-property name = "gwt.logging.popupHandler" value = "DISABLED" />
Use logger to log user actions
/* Create Root Logger */ private static Logger rootLogger = Logger.getLogger(""); ... rootLogger.log(Level.SEVERE, "pageIndex selected: " + event.getValue()); ...
Logging Framework Example
這個示例將引導您通過簡單的步驟來演示GWT應用程式的日誌記錄功能。按照以下步驟更新我們在GWT-Create application−一章中創建的GWT應用程式;
Step | Description |
---|---|
1 | Create a project with a name HelloWorld under a package com.tutorialspoint as explained in the GWT - Create Application chapter. |
2 | Modify HelloWorld.gwt.xml, HelloWorld.css, HelloWorld.html and HelloWorld.java as explained below. Keep rest of the files unchanged. |
3 | Compile and run the application to verify the result of the implemented logic. |
下面是修改後的模塊描述符的內容。
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <inherits name = "com.google.gwt.logging.Logging"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> <set-property name = "gwt.logging.logLevel" value="SEVERE"/> <set-property name = "gwt.logging.enabled" value = "TRUE"/> <set-property name = "gwt.logging.popupHandler" value= "DISABLED" /> </module>
下面是修改後的樣式表文件war/HelloWorld.css的內容。
body { text-align: center; font-family: verdana, sans-serif; } h1 { font-size: 2em; font-weight: bold; color: #777777; margin: 40px 0px 70px; text-align: center; }
下面是修改後的HTML宿主文件war/HelloWorld.HTML的內容
<html> <head> <title>Hello World</title> <link rel = "stylesheet" href = "HelloWorld.css"/> <script language = "javascript" src = "helloworld/helloworld.nocache.js"> </script> </head> <body> <iframe src = "javascript:''"id = "__gwt_historyFrame" style = "width:0;height:0;border:0"></iframe> <h1> Logging Demonstration</h1> <div id = "gwtContainer"></div> </body> </html>
package com.tutorialspoint.client; import java.util.logging.Level; import java.util.logging.Logger; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.logging.client.HasWidgetsLogHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Hyperlink; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.VerticalPanel; public class HelloWorld implements EntryPoint { private TabPanel tabPanel; /* Create Root Logger */ private static Logger rootLogger = Logger.getLogger(""); private VerticalPanel customLogArea; private void selectTab(String historyToken){ /* parse the history token */ try { if (historyToken.substring(0, 9).equals("pageIndex")) { String tabIndexToken = historyToken.substring(9, 10); int tabIndex = Integer.parseInt(tabIndexToken); /* Select the specified tab panel */ tabPanel.selectTab(tabIndex); } else { tabPanel.selectTab(0); } } catch (IndexOutOfBoundsException e) { tabPanel.selectTab(0); } } /** * This is the entry point method. */ public void onModuleLoad() { /* create a tab panel to carry multiple pages */ tabPanel = new TabPanel(); /* create pages */ HTML firstPage = new HTML("<h1>We are on first Page.</h1>"); HTML secondPage = new HTML("<h1>We are on second Page.</h1>"); HTML thirdPage = new HTML("<h1>We are on third Page.</h1>"); String firstPageTitle = "First Page"; String secondPageTitle = "Second Page"; String thirdPageTitle = "Third Page"; Hyperlink firstPageLink = new Hyperlink("1", "pageIndex0"); Hyperlink secondPageLink = new Hyperlink("2", "pageIndex1"); Hyperlink thirdPageLink = new Hyperlink("3", "pageIndex2"); HorizontalPanel linksHPanel = new HorizontalPanel(); linksHPanel.setSpacing(10); linksHPanel.add(firstPageLink); linksHPanel.add(secondPageLink); linksHPanel.add(thirdPageLink); /* If the application starts with no history token, redirect to a pageIndex0 */ String initToken = History.getToken(); if (initToken.length() == 0) { History.newItem("pageIndex0"); initToken = "pageIndex0"; } tabPanel.setWidth("400"); /* add pages to tabPanel*/ tabPanel.add(firstPage, firstPageTitle); tabPanel.add(secondPage,secondPageTitle); tabPanel.add(thirdPage, thirdPageTitle); /* add value change handler to History * this method will be called, when browser's Back button * or Forward button are clicked. * and URL of application changes. * */ History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { selectTab(event.getValue()); rootLogger.log(Level.SEVERE, "pageIndex selected: " + event.getValue()); } }); selectTab(initToken); VerticalPanel vPanel = new VerticalPanel(); vPanel.setSpacing(10); vPanel.add(tabPanel); vPanel.add(linksHPanel); customLogArea = new VerticalPanel(); vPanel.add(customLogArea); /* an example of using own custom logging area. */ rootLogger.addHandler(new HasWidgetsLogHandler(customLogArea)); /* add controls to RootPanel */ RootPanel.get().add(vPanel); } }
完成所有更改後,讓我們以開發模式編譯並運行應用程式,就像我們在「gwt-創建應用程式」一章中所做的那樣。如果你的申請一切順利,這將產生以下結果;
現在單擊1、2或3。您可以注意到,當您單擊1、2或3時,您可以看到顯示頁面索引的日誌正在列印。檢查Eclipse中的控制台輸出。您還可以在Eclipse控制台中看到日誌正在列印。
Fri Aug 31 11:42:35 IST 2012 SEVERE: pageIndex selected: pageIndex0 Fri Aug 31 11:42:37 IST 2012 SEVERE: pageIndex selected: pageIndex1 Fri Aug 31 11:42:38 IST 2012 SEVERE: pageIndex selected: pageIndex2 Fri Aug 31 11:42:40 IST 2012 SEVERE: pageIndex selected: pageIndex0 Fri Aug 31 11:42:41 IST 2012 SEVERE: pageIndex selected: pageIndex1 Fri Aug 31 11:42:41 IST 2012 SEVERE: pageIndex selected: pageIndex2
<?xml version = "1.0" encoding = "UTF-8"?> <module rename-to = 'helloworld'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name = 'com.google.gwt.user.User'/> <!-- Inherit the default GWT style sheet. --> <inherits name = 'com.google.gwt.user.theme.clean.Clean'/> <inherits name = "com.google.gwt.logging.Logging"/> <!-- Specify the app entry point class. --> <entry-point class = 'com.tutorialspoint.client.HelloWorld'/> <!-- Specify the paths for translatable code --> <source path = 'client'/> <source path = 'shared'/> <set-property name = "gwt.logging.logLevel" value = "SEVERE"/> <set-property name = "gwt.logging.enabled" value = "TRUE"/> <set-property name="gwt.logging.popupHandler" value = "ENABLED" /> </module>
完成所有更改後,通過刷新瀏覽器窗口(按瀏覽器的F5/重新加載按鈕)重新加載應用程式。注意應用程式的左上角現在有一個彈出窗口。
現在單擊1、2或3。您可以注意到,當您單擊1、2或3時,您可以看到正在列印的日誌在彈出窗口中顯示頁面索引。