GWT - 快速指南
GWT - Overview
什么是GWT?
Google Web Toolkit(GWT)是一个用于创建RICH Internet Applications (RIA)的开发工具包。 以下是一些值得注意的功能 -
GWT为开发人员提供了在JAVA中编写客户端应用程序的选项。
GWT将用JAVA编写的代码编译为JavaScript代码。
用GWT编写的应用程序是跨浏览器兼容的。 GWT自动生成适合每个浏览器的javascript代码。
GWT是开源的,完全免费的,并被全球数千名开发人员使用。 它是根据Apache许可证2.0版许可的。
总体而言,GWT是一个构建大规模和高性能Web应用程序的framework ,同时使它们易于维护。
为什么要使用GWT?
基于Java,您可以使用Eclipse等JAVA IDE来开发GWT应用程序。
开发人员可以使用代码自动完成/重构/导航/项目管理以及IDEs.GWT的所有功能,它提供完整的调试功能。 开发人员可以像Java应用程序一样调试客户端应用程序。
GWT提供与Junit和Maven的轻松集成。
作为基于Java的,GWT对Java开发人员的学习曲线较低。
GWT生成优化的javascript代码,自己生成浏览器的特定javascript代码。
GWT提供的Widgets库提供了应用程序所需的大部分任务。
GWT是可扩展的,可以创建自定义小部件以满足应用程序需求。
最重要的是,GWT应用程序可以在所有主流浏览器和智能手机上运行,包括基于Android和iOS的手机/平板电脑。
GWT的缺点
虽然GWT提供了很多优点,但它有以下缺点 -
Not Indexable - GWT生成的网页不会被搜索引擎索引,因为这些应用程序是动态生成的。
Not Degradable - 如果您的应用程序用户禁用Javascript,那么用户只会看到基本页面而已。
Not Designer's Friendly - GWT不适合那些喜欢使用普通HTML和占位符来在以后插入动态内容的网页设计师。
GWT组件
GWT框架可分为以下三个主要部分 -
GWT Java to JavaScript compiler - 这是GWT最重要的部分,使其成为构建RIA的强大工具。 GWT编译器用于将用Java编写的所有应用程序代码转换为JavaScript。
JRE Emulation library - Google Web Toolkit包含一个模拟Java运行时库子集的库。 该列表包括java.lang,java.lang.annotation,java.math,java.io,java.sql,java.util和java.util.logging
GWT UI building library - GWT的这一部分由许多子部分组成,其中包括实际的UI组件,RPC支持,历史记录管理等等。
GWT还提供了一个GWT托管Web浏览器,它允许您以托管模式运行和执行GWT应用程序,其中您的代码在Java虚拟机中作为Java运行,而无需编译为JavaScript。
GWT - Environment Setup
本教程将指导您如何准备开发环境以开始使用GWT Framework。 本教程还将教您如何在设置GWT框架之前在您的机器上设置JDK,Tomcat和Eclipse -
系统需求 (System Requirement)
GWT需要JDK 1.6或更高版本,因此第一个要求是在您的计算机上安装JDK。
JDK | 1.6或以上。 |
---|---|
记忆 | 没有最低要求。 |
磁盘空间 | 没有最低要求。 |
操作系统 | 没有最低要求。 |
按照给定的步骤设置环境以开始GWT应用程序开发。
步骤1 - 验证计算机上的Java安装
现在打开控制台并执行以下java命令。
OS | 任务 | 命令 |
---|---|---|
Windows | 打开命令控制台 | c:\> java -version |
Linux | 打开命令终端 | $ java -version |
Mac | 开放式终端 | 机器:~joseph $ java -version |
让我们验证所有操作系统的输出
Sr.No. | 操作系统和生成的输出 |
---|---|
1 | Windows java版“1.6.0_21” Java(TM)SE运行时环境(版本1.6.0_21-b07) Java HotSpot(TM)客户端VM(版本17.0-b17,混合模式,共享) |
2 | Linux java版“1.6.0_21” Java(TM)SE运行时环境(版本1.6.0_21-b07) ava HotSpot(TM)客户端VM(版本17.0-b17,混合模式,共享) |
3 | Mac java版“1.6.0_21” Java(TM)SE运行时环境(版本1.6.0_21-b07) Java HotSpot(TM)64位服务器VM(内置17.0-b17,混合模式,共享) |
第2步 - 安装Java开发工具包(JDK)
如果您没有安装Java,那么您可以从Oracle的Java站点安装Java软件开发工具包(SDK): Java SE下载 。 您将找到有关在下载文件中安装JDK的说明,请按照给出的说明安装和配置设置。 最后设置PATH和JAVA_HOME环境变量来引用包含java和javac的目录,通常分别是java_install_dir/bin和java_install_dir。
将JAVA_HOME环境变量设置为指向计算机上安装Java的基本目录位置。 例如
Sr.No. | 操作系统和输出 |
---|---|
1 | Windows 将环境变量JAVA_HOME设置为C:\Program Files\Java\jdk1.6.0_21 |
2 | Linux export JAVA_HOME =/usr/local/java-current |
3 | Mac export JAVA_HOME =/Library/Java/Home |
将Java编译器位置附加到系统路径。
Sr.No. | 操作系统和输出 |
---|---|
1 | Windows 将字符串;%JAVA_HOME%\ bin附加到系统变量Path的末尾。 |
2 | Linux export PATH = $ PATH:$ JAVA_HOME/bin/ |
3 | Mac 不需要 |
或者,如果您使用Borland JBuilder,Eclipse,IntelliJ IDEA或Sun ONE Studio等集成开发环境(IDE),请编译并运行一个简单程序以确认IDE知道您在何处安装Java,否则请按照给定文档进行正确设置的IDE。
第3步 - 安装Eclipse IDE
本教程中的所有示例都是使用Eclipse IDE编写的。 因此,我建议您根据操作系统在计算机上安装最新版本的Eclipse。
要安装Eclipse IDE,请从https://www.eclipse.org/downloads/下载最新的Eclipse二进制文件。 下载安装后,将二进制分发包解压到一个方便的位置。 例如,在Windows上的C:\eclipse或Linux/Unix上的/ usr/local/eclipse中,最后适当地设置PATH变量。
可以通过在Windows机器上执行以下命令来启动Eclipse,或者只需双击eclipse.exe即可
%C:\eclipse\eclipse.exe
可以通过在Unix(Solaris,Linux等)机器上执行以下命令来启动Eclipse -
$/usr/local/eclipse/eclipse
成功启动后,如果一切正常,那么它应显示以下结果 -
第4步:为Eclipse安装GWT SDK和插件
按照Eclipse插件(包括SDK)链接中的说明安装机器上安装的Eclipse版本的GWT SDK和插件。
成功设置GWT插件后,如果一切正常,则应显示以下屏幕,其中Google icon标有红色矩形,如下所示 -
第5步:设置Apache Tomcat
您可以从https://tomcat.apache.org/下载最新版本的Tomcat。 下载安装后,将二进制分发包解压到一个方便的位置。 例如,在Windows上的C:\apache-tomcat-6.0.33或Linux/Unix上的/usr/local/apache-tomcat-6.0.33中,并设置指向安装位置的CATALINA_HOME环境变量。
可以通过在Windows机器上执行以下命令来启动Tomcat,也可以只需双击startup.bat即可
%CATALINA_HOME%\bin\startup.bat
or
C:\apache-tomcat-6.0.33\bin\startup.bat
成功启动后,Tomcat附带的默认Web应用程序将通过访问http://localhost:8080/ 。 如果一切都很好,那么它应该显示以下结果 -
有关配置和运行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应用程序包含以下四个重要部分,其中最后一部分是可选的,但前三部分是必需的。
- 模块描述符
- 公共资源
- 客户端代码
- 服务器端代码
典型gwt应用程序HelloWord的不同部分的样本位置如下所示 -
名称 | 地点 |
---|---|
Project root | HelloWorld/ |
模块描述符 | src/com/iowiki/HelloWorld.gwt.xml |
公共资源 | src/com/iowiki/war/ |
客户端代码 | src/com/iowiki/client/ |
服务器端代码 | src/com/iowiki/server/ |
模块描述符
模块描述符是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.iowiki.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. | 节点和描述 |
---|---|
1 | 《module rename-to = "helloworld"》 这提供了应用程序的名称。 |
2 | 《inherits name = "logical-module-name" /》 这在应用程序中添加了其他gwt模块,就像java应用程序中的import一样。 可以以这种方式继承任意数量的模块。 |
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 | 《stylesheet src="css-url" /》 自动注入位于src指定位置的外部CSS文件。 |
公共资源
这些是GWT模块引用的所有文件,例如主机HTML页面,CSS或图像。
可以使用模块配置文件中的
将应用程序编译为JavaScript时,可以在公共路径中找到的所有文件都复制到模块的输出目录中。
最重要的公共资源是主页,用于调用实际的GWT应用程序。 应用程序的典型HTML主机页面可能根本不包含任何可见的HTML正文内容,但总是希望通过标记包含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,最终将在浏览器中运行。 可以使用模块配置文件中的
例如, Entry Point代码将用作客户端代码,其位置将使用“source path =”path“/”指定。
模块entry-point是可分配给EntryPoint任何类,可以在没有参数的情况下构造。 加载模块时,将实例化每个入口点类并调用其EntryPoint.onModuleLoad()方法。 HelloWorld入口点示例类如下 -
public class HelloWorld implements EntryPoint {
public void onModuleLoad() {
Window.alert("Hello, World!");
}
}
服务器端代码
这是应用程序的服务器端部分,非常可选。 如果您没有在应用程序中进行任何后端处理,那么您不需要此部分,但如果后端需要某些处理并且您的客户端应用程序与服务器交互,那么您将不得不开发这些组件。
下一章将利用上述所有概念,使用Eclipse IDE创建HelloWorld应用程序。
GWT - Create Application
由于GWT的功能在于使用Java Write in Java, Run in JavaScript , Write in Java, Run in JavaScript ,我们将使用Java IDE Eclipse来演示我们的示例。
让我们从一个简单的HelloWorld应用程序开始 -
第1步 - 创建项目
第一步是使用Eclipse IDE创建一个简单的Web应用程序项目。 使用Google Icon 》 New Web Application Project...选项启动项目向导 Google Icon 》 New Web Application Project... Google Icon 》 New Web Application Project... 现在使用向导窗口将项目命名为HelloWorld ,如下所示 -
取消选择Use Google App Engine因为我们没有在此项目中使用它并保留其他默认值(保持选中Generate Sample project code选项)并单击Finish按钮。
成功创建项目后,您将在Project Explorer中拥有以下内容 -
以下是所有重要文件夹的简要说明
Sr.No. | 文件夹和位置 |
---|---|
1 | src 源代码(java类)文件。 客户端文件夹,包含负责客户端UI显示的客户端特定Java类。 服务器文件夹,包含负责服务器端处理的服务器端java类。 包含java模型类的共享文件夹,用于将数据从服务器传输到客户端,反之亦然。 HelloWorld.gwt.xml,GWT编译器编译HelloWorld项目所需的模块描述符文件。 |
2 | test 测试代码(java类)源文件。 客户端文件夹,包含负责测试gwt客户端代码的java类。 |
3 | war 这是最重要的部分,它代表了实际可部署的Web应用程序。 WEB-INF包含已编译的类,gwt库,servlet库。 HelloWorld.css,项目样式表。 HelloWorld.html,hots HTML将调用GWT UI Application。 |
第2步 - 修改模块描述符:HelloWorld.gwt.xml
GWT插件将创建一个默认模块描述符文件src/com.iowiki/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.iowiki.client.HelloWorld'/>
<!-- Specify the paths for translatable code -->
<source path = 'client'/>
<source path = 'shared'/>
</module>
第3步 - 修改样式表: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;
}
第4步 - 修改主机文件: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或图像,也可以创建更多子目录并在这些子目录中移动文件,并在应用程序的模块描述符中配置这些子目录。
第5步 - 修改入口点:HelloWorld.java
GWT插件将创建一个默认的Java文件src/com.iowiki/HelloWorld.java ,它保留了应用程序的入口点。
让我们修改此文件以显示“Hello,World!”
package com.iowiki.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文件,以定义入口点或定义帮助程序例程。
第6步 - 编译应用程序
一旦准备好完成所有更改,就可以编译项目了。 使用Google Icon 》 GWT Compile Project...选项 Google Icon 》 GWT Compile Project... Google Icon 》 GWT Compile Project...启动GWT Compile对话框,如下图所示 -
保持默认值不变,然后单击“编译”按钮。 如果一切顺利,您将在Eclipse控制台中看到以下输出
Compiling module com.iowiki.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
第7步 - 运行应用程序
现在点击 运行应用程序菜单并选择HelloWorld应用程序以运行该应用程序。
如果一切正常,您必须在Eclipse中看到包含URL的GWT开发模式,如下所示。 双击URL以打开GWT应用程序。
因为您在开发模式下运行应用程序,所以您需要为浏览器安装GWT插件。 只需按照屏幕上的说明安装插件即可。
如果您已经为浏览器设置了GWT插件,那么您应该能够看到以下输出
恭喜! 您已使用Google Web Toolkit(GWT)实施了第一个应用程序。
GWT - Deploy Application
本教程将向您解释如何创建应用程序"war"文件以及如何在Apache Tomcat Websever根目录中部署它。
如果您理解了这个简单的示例,那么您还可以按照相同的步骤部署复杂的GWT应用程序。
让我们使用Eclipse IDE和GWT插件,并按照以下步骤创建GWT应用程序 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以确保业务逻辑按照要求运行。 |
4 | 最后,以war文件的形式压缩应用程序的war文件夹的内容,并将其部署在Apache Tomcat Webserver中。 |
5 | 使用适当的URL启动Web应用程序,如下面的最后一步所述。 |
以下是修改后的模块描述符src/com.iowiki/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.iowiki.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>
我从前面的例子中稍微修改了一下HTML。 在这里,我创建了一个占位符
package com.iowiki.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 - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -
创建WAR文件
现在我们的应用程序运行正常,我们准备将其导出为war文件。
请按照以下步骤操作 -
进入项目的war目录C:\workspace\HelloWorld\war
选择war目录中可用的所有文件和文件夹。
将所有选定的文件和文件夹压缩到名为HelloWorld.zip的文件中。
将HelloWorld.zip重命名为HelloWorld.war 。
部署WAR文件
停止tomcat服务器。
将HelloWorld.war文件复制到tomcat installation directory 》 webapps folder.
启动tomcat服务器。
查看webapps目录,应该创建一个helloworld文件夹。
现在HelloWorld.war已成功部署在Tomcat Webserver根目录中。
运行应用程序
在Web浏览器中输入URL: http://localhost:8080/HelloWorld以启动应用程序
服务器名称(localhost)和端口(8080)可能因tomcat配置而异。
GWT - Style with CSS
GWT小部件依赖于级联样式表(CSS)来实现视觉样式。 默认情况下,每个组件的类名是gwt-《classname》 。
例如,Button小部件的默认样式为gwt-Button ,类似的方式TextBox widgest的默认样式为gwt-TextBox 。
为了给所有按钮和文本框添加更大的字体,您可以将以下规则放在应用程序的CSS文件中
.gwt-Button { font-size: 150%; }
.gwt-TextBox { font-size: 150%; }
默认情况下,浏览器和GWT都不为窗口小部件创建默认的id属性。 您必须为可在CSS中使用的元素显式创建唯一ID。 为了给id为my-button-id的特定按钮提供更大的字体,你可以将以下规则放在应用程序的CSS文件中 -
#my-button-id { font-size: 150%; }
要设置GWT窗口小部件的ID,请检索其DOM元素,然后按如下所示设置id属性 -
Button b = new Button();
DOM.setElementAttribute(b.getElement(), "id", "my-button-id")
CSS样式API
有许多API可用于为任何GWT小部件挂起CSS设置。 以下几个重要的API将帮助您使用GWT进行日常Web编程 -
Sr.No. | API和说明 |
---|---|
1 | public void setStyleName(java.lang.String style) 此方法将清除任何现有样式,并将窗口小部件样式设置为使用style提供的新CSS类。 |
2 | public void addStyleName(java.lang.String style) 此方法将向窗口小部件添加辅助或从属样式名称。 辅助样式名称是另一个样式名称,因此如果应用了任何先前的样式名称,则会保留它们。 |
3 | public void removeStyleName(java.lang.String style) 此方法将从窗口小部件中删除给定样式,并保留与窗口小部件关联的任何其他样式 |
4 | public java.lang.String getStyleName() 此方法获取所有对象的样式名称,作为以空格分隔的列表。 |
5 | public void setStylePrimaryName(java.lang.String style) 此方法设置对象的主样式名称并更新所有相关样式名称。 |
例如,让我们定义两个我们将应用于文本的新样式 -
.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 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");
关联CSS文件
有多种方法可以将CSS文件与模块相关联。 现代GWT应用程序通常使用CssResource和UiBinder的组合。 我们在示例中仅使用第一种方法。
在主机HTML页面中使用标记。
使用模块XML文件中的
元素。 使用ClientBundle包含的CssResource 。
在UiBinder模板中使用内联<ui:style>元素。
GWT CSS示例
此示例将指导您完成在GWT widgest上应用不同CSS规则的简单步骤。 让我们使用Eclipse IDE和GWT插件,并按照以下步骤创建GWT应用程序 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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.iowiki.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主机文件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>
<div id = "mytext"><h1>Hello, World!</h1></div>
<div id = "gwtGreenButton"></div>
<div id = "gwtRedButton"></div>
</body>
</html>
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,它将负责在HTML中添加两个按钮,并将应用自定义CSS样式。
package com.iowiki.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 - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -
现在点击显示的两个按钮,观察“Hello,World!” 单击两个按钮时不断更改字体的文本。
GWT - Basic Widgets
每个用户界面都考虑以下三个主要方面 -
UI elements - 这是用户最终看到并与之交互的核心视觉元素。 GWT提供了大量广泛使用的常用元素,从基本到复杂,我们将在本教程中介绍。
Layouts - 它们定义了如何在屏幕上组织UI元素,并为GUI(图形用户界面)提供最终外观。 这一部分将在布局章节中介绍。
Behavior - 这些是用户与UI元素交互时发生的事件。 这部分将在事件处理章节中介绍。
GWT UI元素
GWT库在明确定义的类层次结构中提供类,以创建复杂的基于Web的用户界面。 此组件层次结构中的所有类都是从UIObject基类派生的,如下所示 -
每个Basic UI小部件都从Widget类继承属性,Widget类继承UIObject的属性。 树和菜单将包含在复杂的小部件教程中。
Sr.No. | 小部件和描述 |
---|---|
1 | GWT UIObject类 此窗口小部件包含文本,不使用 元素解释为HTML,从而使其以块布局显示。 |
2 | GWT Widget类 此窗口小部件可以包含HTML文本,并使用 元素显示html内容,使其以块布局显示。 |
基本小部件
以下是几个重要的Basic Widgets -
Sr.No. | 小部件和描述 |
---|---|
1 | Label 此窗口小部件包含文本,不使用 元素解释为HTML,从而使其以块布局显示。 |
2 | HTML 此窗口小部件可以包含HTML文本,并使用 元素显示html内容,使其以块布局显示。 |
3 | Image 此小组件显示给定URL的图像。 |
4 | Anchor 此小部件表示一个简单的元素。 |
GWT - Form Widgets
表单小部件允许用户输入数据并为应用程序提供交互功能。 每个Form小部件都从Widget类继承属性,Widget类继承UIObject和Wigdet类的属性。
Sr.No. | 小部件和描述 |
---|---|
1 | GWT UIObject类 此窗口小部件包含文本,不使用 元素解释为HTML,从而使其以块布局显示。 |
2 | GWT Widget类 此窗口小部件可以包含HTML文本,并使用 元素显示html内容,使其以块布局显示。 |
表单小部件
以下是几个重要的Form Widgets -
Sr.No. | 小部件和描述 |
---|---|
1 | Button 此小组件代表标准按钮。 |
2 | PushButton 此小组件表示具有自定义样式的常规按钮。 |
3 | ToggleButton 此小部件代表一个时尚的有状态按钮,允许用户在向上和向下状态之间切换。 |
4 | CheckBox 此小组件表示标准复选框小组件。 该类还充当RadioButton的基类。 |
5 | RadioButton 此小组件表示互斥的选择单选按钮小组件。 |
6 | ListBox 此小组件表示用户的选项列表,可以是列表框,也可以是下拉列表。 |
7 | SuggestBox 此小组件表示文本框或文本区域,显示与用户输入匹配的预配置选择集。 每个SuggestBox都与一个SuggestOracle相关联。 SuggestOracle用于在给定特定查询字符串的情况下提供一组选择。 |
8 | TextBox 此小组件表示单行文本框。 |
9 | PasswordTextBox 此窗口小部件表示一个文本框,可以直观地屏蔽其输入以防止窃听。 |
10 | TextArea 此小组件表示允许输入多行文本的文本框。 |
11 | RichTextArea 此小组件表示富文本编辑器,允许复杂的样式和格式。 |
12 | FileUpload 此小部件包装HTML 元素。 |
13 | Hidden 此小部件表示HTML表单中的隐藏字段。 |
GWT - Complex Widgets
“复杂小部件”允许用户与应用程序进行高级交互功能。 每个Complex小部件都从Widget类继承属性,Widget类继承UIObject的属性。
Sr.No. | 小部件和描述 |
---|---|
1 | GWT UIObject类 此窗口小部件包含文本,不使用 元素解释为HTML,从而使其以块布局显示。 |
2 | GWT Widget类 此窗口小部件可以包含HTML文本,并使用 元素显示html内容,使其以块布局显示。 |
复杂小部件
以下是一些重要的复杂小部件 -
Sr.No. | 小部件和描述 |
---|---|
1 | Tree 此小组件表示标准分层树小组件。 树包含TreeItem的层次结构,用户可以打开,关闭和选择。 |
2 | MenuBar 此小组件代表标准菜单栏小部件。 菜单栏可以包含任意数量的菜单项,每个菜单项可以触发命令或打开级联菜单栏。 |
3 | DatePicker 此小组件代表标准GWT日期选择器。 |
4 | CellTree 此小组件表示树的视图。 此小部件仅在标准模式下工作,这要求运行它的HTML页面具有明确的声明。 |
5 | CellList 此小组件表示单个列的单元格列表。 |
6 | CellTable 此小组件表示支持分页和列的表格视图。 |
7 | CellBrowser 此窗口小部件表示树的browsable视图,其中每个级别只能打开一个节点。 此小部件仅在标准模式下工作,这要求运行它的HTML页面具有明确的“!DOCTYPE”声明。 |
GWT - Layout Panels
布局面板可以包含其他小部件。 这些面板控制在用户界面上显示小部件的方式。 每个Panel小部件都从Panel类继承属性,而Panel类继承Widget类的属性,而后者继承UIObject类的属性。
Sr.No. | 小部件和描述 |
---|---|
1 | GWT UIObject类 此窗口小部件包含文本,不使用 元素解释为HTML,从而使其以块布局显示。 |
2 | GWT Widget类 此窗口小部件可以包含HTML文本,并使用 元素显示html内容,使其以块布局显示。 |
3 | GWT小组课程 这是所有面板的抽象基类,它是可以包含其他小部件的小部件。 |
布局面板
以下是几个重要的Layout Panels -
Sr.No. | 小部件和描述 |
---|---|
1 | FlowPanel 此窗口小部件表示使用默认HTML布局行为格式化其子窗口小部件的面板。 |
2 | HorizontalPanel 此窗口小部件表示一个面板,它将所有窗口小部件放在一个水平列中。 |
3 | VerticalPanel 此窗口小部件表示一个面板,它将所有窗口小部件放在一个垂直列中。 |
4 | HorizontalSplitPanel 此窗口小部件表示一个面板,它在单个水平行中排列两个窗口小部件,并允许用户以交互方式更改专用于两个窗口小部件中每个窗口小部件的宽度比例。 必要时,HorizontalSplitPanel中包含的小部件将使用滚动条自动修饰。 |
5 | VerticalSplitPanel 此窗口小部件表示一个A面板,它在单个垂直列中排列两个窗口小部件,并允许用户以交互方式更改专用于两个窗口小部件中每个窗口小部件的高度比例。 VertialSplitPanel中包含的小部件将在必要时使用滚动条自动修饰。 |
6 | FlexTable 此小组件表示一个灵活的表,可按需创建单元格。 它可以是锯齿状的(也就是说,每行可以包含不同数量的单元格),并且可以将单个单元格设置为跨越多个行或列。 |
7 | Grid 此窗口小部件表示一个矩形网格,可以在其单元格中包含文本,html或子窗口小部件。 必须将其显式调整为所需的行数和列数。 |
8 | DeckPanel 在“套牌”中显示其所有子窗口小部件的面板,其中一次只能看到一个。 它由TabPanel使用。 |
9 | DockPanel 此小部件表示一个面板,该面板将其子窗口小部件“停靠”在其外边缘,并允许其最后一个窗口小部件占用其中心的剩余空间。 |
10 | HTMLPanel 此窗口小部件表示包含HTML的面板,可以将子窗口小部件附加到该HTML中的已标识元素。 |
11 | TabPanel 此小组件表示一个面板,该面板表示一组选项卡式页面,每个页面都包含另一个小部件。 当用户选择与其关联的各种选项卡时,将显示其子窗口小部件。 选项卡可以包含任意HTML。 |
12 | Composite 此窗口小部件表示一种窗口小部件,可以包装另一个窗口小部件,隐藏包装窗口小部件的方法。 添加到面板时,复合体的行为就像添加了它包装的窗口小部件一样。 |
13 | SimplePanel 此窗口小部件表示仅包含一个窗口小部件的面板的基类。 |
14 | ScrollPanel 此小组件表示一个简单的面板,它将其内容包装在可滚动区域中 |
15 | FocusPanel 此小部件表示一个简单的面板,使其内容可聚焦,并添加捕获鼠标和键盘事件的功能。 |
16 | FormPanel 此小组件表示将其内容包装在HTML |
17 | PopupPanel 此窗口小部件表示可以pop up其他窗口小部件的面板。 它覆盖了浏览器的客户区(以及任何以前创建的弹出窗口)。 |
18 | DialogBox 此窗口小部件表示一种弹出窗口,其顶部有一个标题区域,可由用户拖动。 与PopupPanel不同,对PopupPanel.setWidth(String)和PopupPanel.setHeight(String)的调用将设置对话框本身的宽度和高度,即使尚未添加窗口小部件。 |
GWT - Event Handling
GWT提供类似于Java AWT或SWING用户界面框架的事件处理程序模型。
侦听器接口定义窗口小部件调用以宣告事件的一个或多个方法。 GWT提供与各种可能事件对应的接口列表。
希望接收特定类型事件的类实现关联的处理程序接口,然后将对其自身的引用传递给窗口小部件以订阅一组事件。
例如, Button类发布click events因此您必须编写一个类来实现ClickHandler来处理click事件。
事件处理程序接口
所有GWT事件处理程序都已从EventHandler接口扩展,并且每个处理程序只有一个带有单个参数的方法。 此参数始终是关联事件类型的对象。 每个event对象都有许多方法来操纵传递的事件对象。 例如,对于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!");
}
}
现在任何希望接收点击事件的类都会调用addClickHandler()来注册事件处理程序,如下所示 -
/**
* create button and attach click handler
*/
Button button = new Button("Click Me!");
button.addClickHandler(new MyClickHandler());
支持事件类型的每个小部件将具有HandlerRegistration形式的方法添加Foo Handler( Foo事件),其中Foo是实际事件,如Click,Error,KeyPress等。
以下是重要的GWT事件处理程序和相关事件以及处理程序注册方法的列表 -
Sr.No. | 事件接口 | 事件方法和描述 |
---|---|---|
1 | 在选择处理程序之前 | void on Before Selection (Before Selection Event《I》 event); 在触发BeforeSelectionEvent时调用。 |
2 | BlurHandler | void on Blur(Blur Event event); 在模糊事件被触发时调用。 |
3 | ChangeHandler | void on Change(ChangeEvent event); 触发更改事件时调用。 |
4 | ClickHandler | void on Click(ClickEvent event); 触发本机点击事件时调用。 |
5 | CloseHandler<T> | void on Close(CloseEvent《T》 event); 在触发CloseEvent时调用。 |
6 | 上下文菜单处理程序 | void on Context Menu(Context Menu Event event); 在触发本机上下文菜单事件时调用。 |
7 | 双击处理程序 | void on Double Click(Double Click Event event); 触发双击事件时调用。 |
8 | 错误处理程序 | void on Error(Error Event event); 触发错误事件时调用。 |
9 | 焦点处理程序 | void on Focus(Focus Event event); 在Focus事件被触发时调用。 |
10 | Form Panel.Submit Complete Handler | void on Submit Complete(Form Panel.Submit Complete Event event); 成功提交表单时触发。 |
11 | FormPanel.SubmitHandler | void on Submit(Form Panel.Submit Event event); 提交表单时触发。 |
12 | 按键处理程序 | void on Key Down(Key Down Event event); 在触发KeyDownEvent时调用。 |
13 | KeyPressHandler | void on KeyPress(KeyPressEvent event); 触发KeyPressEvent时调用。 |
14 | KeyUpHandler | void on KeyUp(KeyUpEvent event); 在触发KeyUpEvent时调用。 |
15 | LoadHandler | void on Load(LoadEvent event); 在触发LoadEvent时调用。 |
16 | MouseDownHandler | void on MouseDown(MouseDownEvent event); 在MouseDown被触发时调用。 |
17 | MouseMoveHandler | void on MouseMove(MouseMoveEvent event); 在触发MouseMoveEvent时调用。 |
18 | MouseOutHandler | void on MouseOut(MouseOutEvent event); 在触发MouseOutEvent时调用。 |
19 | MouseOverHandler | void on MouseOver(MouseOverEvent event); 在触发MouseOverEvent时调用。 |
20 | MouseUpHandler | void on MouseUp(MouseUpEvent event); 在MouseUpEvent被触发时调用。 |
21 | MouseWheelHandler | void on MouseWheel(MouseWheelEvent event); 在触发MouseWheelEvent时调用。 |
22 | ResizeHandler | void on Resize(ResizeEvent event); 调整窗口小部件时触发。 |
23 | ScrollHandler | void on Scroll(ScrollEvent event); 触发ScrollEvent时调用。 |
24 | SelectionHandler<I> | void on Selection(SelectionEvent《I》 event); 在SelectionEvent被触发时调用。 |
25 | ValueChangeHandler<I> | void on ValueChange(ValueChangeEvent《I》 event); 触发ValueChangeEvent时调用。 |
26 | Window.ClosingHandler | void on WindowClosing(Window.ClosingEvent event); 在浏览器窗口关闭或导航到其他站点之前触发。 |
27 | Window.ScrollHandler | void on WindowScroll(Window.ScrollEvent event); 滚动浏览器窗口时触发。 |
事件方法
如前所述,每个处理程序都有一个方法,其中包含一个保存事件对象的参数,例如void onClick(ClickEvent event)或void onKeyDown(KeyDownEvent event) 。 ClickEvent和KeyDownEvent等事件对象的常用方法很少,如下所示 -
Sr.No. | 方法和描述 |
---|---|
1 | protected void dispatch(ClickHandler handler)此方法只能由HandlerManager调用 |
2 | DomEvent.Type 《FooHandler》 getAssociatedType()此方法返回用于注册Foo事件的类型。 |
3 | static DomEvent.Type《FooHandler》 getType()此方法获取与Foo事件关联的事件类型。 |
4 | public java.lang.Object getSource()此方法返回上次触发此事件的源。 |
5 | protected final boolean isLive()此方法返回事件是否为活动。 |
6 | protected void kill()此方法终止事件 |
例子 (Example)
此示例将指导您完成在GWT中显示Click事件和KeyDown事件处理的使用的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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.iowiki.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>
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,它将演示在GWT中使用事件处理。
package com.iowiki.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提供了三种创建自定义用户界面元素的方法。 有三种一般策略可供遵循 -
Create a widget by extending Composite Class - 这是创建自定义小部件的最常用和最简单的方法。 在这里,您可以使用现有小部件来创建具有自定义属性的复合视图。
Create a widget using GWT DOM API in JAVA - 以这种方式创建GWT基本窗口小部件。 仍然是创建自定义小部件的一种非常复杂的方式,应谨慎使用。
Use JavaScript and wrap it in a widget using JSNI - 这通常只能作为最后的手段来完成。 考虑到本机方法的跨浏览器含义,它变得非常复杂并且也变得更难以调试。
使用复合类创建自定义小组件
此示例将指导您完成在GWT中创建自定义窗口小部件的简单步骤。 按照以下步骤更新我们在GWT - Basic Widgets章节中创建的GWT应用程序 -
这里我们将通过扩展Composite类来创建自定义小部件,这是构建自定义小部件的最简单方法。
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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.iowiki.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>
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,它将演示Custom小部件的创建。
package com.iowiki.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 - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -
You can notice following points
通过扩展Composite小部件来创建Custom Widget非常简单。
我们使用GWT内置小部件,TextBox和CheckBox创建了一个小部件,因此使用了可重用性的概念。
根据复选框的状态禁用/启用TextBox。 我们提供了一个API来启用/禁用控件。
我们通过记录的CSS样式公开了内部小部件样式。
GWT - UiBinder
介绍 (Introduction)
UiBinder是一个旨在分离功能和用户界面视图的框架。
UiBinder框架允许开发人员将gwt应用程序构建为HTML页面,并在其中配置GWT小部件。
UiBinder框架使与UI设计人员的协作变得更容易,他们比XML源代码更熟悉XML,HTML和CSS
UIBinder提供了一种定义用户界面的声明方式。
UIBinder从UI中分离出程序逻辑。
UIBinder类似于JSP对Servlets的作用。
UiBinder工作流程
第1步:创建UI声明XML文件
创建基于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.iowiki.client.LoginResources'>
<ui:with type = "com.iowiki.client.LoginResources" field = "res">
</ui:with>
<gwt:HTMLPanel>
...
</gwt:HTMLPanel>
</ui:UiBinder>
第2步:使用ui:字段进行后期绑定
使用XML/HTML元素中的ui:field属性将XML中的UI字段与JAVA文件中的UI字段相关联,以便以后绑定。
<gwt:Label ui:field = "completionLabel1" />
<gwt:Label ui:field = "completionLabel2" />
第3步:创建UI XML的Java对应物
通过扩展Composite小部件,创建基于XML的基于XML的布局。 我们在示例中创建了一个Login.java文件。
package com.iowiki.client;
...
public class Login extends Composite {
...
}
步骤4:使用UiField批注绑定Java UI字段
在Login.java使用@UiField注释来指定要在Login.java中绑定到基于XML的字段的对应类成员
public class Login extends Composite {
...
@UiField
Label completionLabel1;
@UiField
Label completionLabel2;
...
}
步骤5:使用带有UiTemplate注释的UI XML绑定Java UI
指示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> {
}
...
}
第6步:创建CSS文件
创建一个外部CSS文件Login.css和基于Java的Resource LoginResources.java文件,相当于css样式
.blackText {
font-family: Arial, Sans-serif;
color: #000000;
font-size: 11px;
text-align: left;
}
...
步骤7:为CSS文件创建基于Java的资源文件
package com.iowiki.client;
...
public interface LoginResources extends ClientBundle {
public interface MyCss extends CssResource {
String blackText();
...
}
@Source("Login.css")
MyCss style();
}
步骤8:在Java UI代码文件中附加CSS资源。
使用基于Java的小部件类Login.java附加外部CSS文件Login.java
public Login() {
this.res = GWT.create(LoginResources.class);
res.style().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
}
UIBinder完整示例
此示例将指导您完成在GWT中显示UIBinder使用情况的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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'/>
<!-- Inherit the UiBinder module. -->
<inherits name = "com.google.gwt.uibinder.UiBinder"/>
<!-- Specify the app entry point class. -->
<entry-point class = 'com.iowiki.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模板和所有者类(文件→新建→UiBinder)。
选择项目的客户端软件包,然后将其命名为Login。 保留所有其他默认值。 单击Finish按钮,插件将创建一个新的UiBinder模板和所有者类。
现在在src/com.iowiki/client包中创建Login.css文件,并在其中放置以下内容
.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;
}
现在在src/com.iowiki/client包中创建LoginResources.java文件并在其中放置以下内容
package com.iowiki.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();
}
使用以下内容替换src/com.iowiki/client包中的src/com.iowiki/client的内容
<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.iowiki.client.LoginResources'>
<ui:with type = "com.iowiki.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>
用以下内容替换src/com.iowiki/client包中的src/com.iowiki/client的内容
package com.iowiki.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("");
}
}
}
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,它将演示UiBinder的使用。
package com.iowiki.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,远程过程调用是GWT使用的机制,其中客户端代码可以直接执行服务器端方法。
GWT RPC是基于servlet的。
GWT RPC是异步的,客户端在通信期间从不被阻止。
使用GWT RPC Java对象可以直接在客户端和服务器之间发送(由GWT框架自动序列化)。
服务器端servlet称为service 。
从客户端代码调用服务器端servlet方法的远程过程调用称为invoking a service 。
GWT RPC组件
以下是GWT RPC通信机制中使用的三个组件
- 在服务器上运行的远程服务(服务器端servlet)。
- 用于调用该服务的客户端代码。
- 将在客户端和服务器之间传递的Java数据对象。
GWT客户端和服务器都自动序列化和反序列化数据,因此开发人员不需要序列化/反序列化对象,数据对象可以通过HTTP传输。
下图显示了RPC体系结构。
要开始使用RPC,我们需要遵循GWT约定。
RPC通信工作流程
第1步:创建可序列化的模型类
在客户端定义一个应该可序列化的java模型对象。
public class Message implements Serializable {
...
private String message;
public Message(){};
public void setMessage(String message) {
this.message = message;
}
...
}
第2步:创建服务接口
在客户端定义服务接口,扩展RemoteService,列出所有服务方法。
使用注释@RemoteServiceRelativePath将服务映射到远程servlet相对于模块基URL的默认路径。
@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
Message getMessage(String input);
}
第3步:创建异步服务接口
在客户端(与上述服务相同的位置)定义一个异步接口,该接口将在GWT客户端代码中使用。
public interface MessageServiceAsync {
void getMessage(String input, AsyncCallback<Message> callback);
}
第4步:创建服务实现Servlet类
在服务器端实现接口,该类应扩展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;
}
}
步骤5:更新Web.xml以包含Servlet声明
编辑Web应用程序部署描述符(web.xml)以包含MessageServiceImpl Servlet声明。
<web-app>
...
<servlet>
<servlet-name>messageServiceImpl</servlet-name>
<servlet-class>com.iowiki.server.MessageServiceImpl
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>messageServiceImpl</servlet-name>
<url-pattern>/helloworld/message</url-pattern>
</servlet-mapping>
</web-app>
步骤6:在应用程序代码中进行远程过程调用
创建服务代理类。
MessageServiceAsync messageService = GWT.create(MessageService.class);
创建AsyncCallback处理程序以处理RPC回调,其中服务器将Message返回给客户端
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通信完整示例
此示例将指导您完成在GWT中显示RPC通信示例的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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'/>
<!-- Inherit the UiBinder module. -->
<inherits name = "com.google.gwt.uibinder.UiBinder"/>
<!-- Specify the app entry point class. -->
<entry-point class = 'com.iowiki.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>
现在在src/com.iowiki/client包中创建Message.java文件,并在其中放置以下内容
package com.iowiki.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;
}
}
现在在src/com.iowiki/client包中创建MessageService.java文件,并在其中放置以下内容
package com.iowiki.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);
}
现在在src/com.iowiki/client包中创建MessageServiceAsync.java文件并在其中放置以下内容
package com.iowiki.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface MessageServiceAsync {
void getMessage(String input, AsyncCallback<Message> callback);
}
现在在src/com.iowiki/server包中创建MessageServiceImpl.java文件并在其中放置以下内容
package com.iowiki.server;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.iowiki.client.Message;
import com.iowiki.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应用程序部署描述符war/WEB-INF/web.xml以包含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.iowiki.server.MessageServiceImpl
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>messageServiceImpl</servlet-name>
<url-pattern>/helloworld/message</url-pattern>
</servlet-mapping>
</web-app>
使用以下内容替换src/com.iowiki/client包中的HelloWorld.java的内容
package com.iowiki.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测试框架为客户端代码的自动测试提供了极好的支持。 在本文中,我们将演示GWT和JUNIT集成。
下载Junit存档
JUnit官方网站 - http://www.junit.org
下载Junit-4.10.jar
OS | 存档名称 |
---|---|
Windows | junit4.10.jar |
Linux | junit4.10.jar |
Mac | junit4.10.jar |
将下载的jar文件存储到计算机上的某个位置。 我们把它存放在C:/ 》 JUNIT
找到GWT安装文件夹
OS | GWT安装文件夹 |
---|---|
Windows | C:\GWT\gwt-2.1.0 |
Linux | /usr/local/GWT/gwt-2.1.0 |
Mac | /Library/GWT/gwt-2.1.0 |
GWTTestCase类
GWT提供了GWTTestCase基类,它提供了JUnit集成。 在JUnit下运行扩展GWTTestCase的编译类会启动HtmlUnit浏览器,该浏览器用于在测试执行期间模拟应用程序行为。
GWTTestCase是来自JUnit的TestCase的派生类,它可以使用JUnit TestRunner运行。
使用webAppCreator
GWT提供了一个特殊的命令行工具webAppCreator ,它可以为我们生成一个入门测试用例,以及用于在开发模式和生产模式下进行测试的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.iowiki.HelloWorld
值得注意的要点
- 我们正在执行webAppCreator命令行实用程序。
- HelloWorld是要创建的项目的名称
- -junit选项指示webAppCreator将junit suppport添加到项目中
- com.iowiki.HelloWorld是模块的名称
验证输出。
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\iowiki
Created directory HelloWorld\src\com\iowiki\client
Created directory HelloWorld\src\com\iowiki\server
Created directory HelloWorld\src\com\iowiki\shared
Created directory HelloWorld\test\com\iowiki
Created directory HelloWorld\test\com\iowiki\client
Created file HelloWorld\src\com\iowiki\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\iowiki\client\HelloWorld.java
Created file
HelloWorld\src\com\iowiki\client\GreetingService.java
Created file
HelloWorld\src\com\iowiki\client\GreetingServiceAsync.java
Created file
HelloWorld\src\com\iowiki\server\GreetingServiceImpl.java
Created file HelloWorld\src\com\iowiki\shared\FieldVerifier.java
Created file HelloWorld\build.xml
Created file HelloWorld\README.txt
Created file HelloWorld\test\com\iowiki\HelloWorldJUnit.gwt.xml
Created file HelloWorld\test\com\iowiki\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
理解测试类:HelloWorldTest.java
package com.iowiki.client;
import com.iowiki.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.iowiki.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. | 注意 |
---|---|
1 | HelloWorldTest类是在HelloWorld/test目录下的com.iowiki.client包中生成的。 |
2 | HelloWorldTest类将包含HelloWorld的单元测试用例。 |
3 | HelloWorldTest类扩展了com.google.gwt.junit.client包中的GWTTestCase类。 |
4 | HelloWorldTest类有一个抽象方法(getModuleName),它必须返回GWT模块的名称。 对于HelloWorld,这是com.iowiki.HelloWorldJUnit。 |
5 | 生成HelloWorldTest类有两个示例测试用例testFieldVerifier,testSimple。 我们添加了testGreetingService。 |
6 | 这些方法使用从JUnit Assert类继承的许多assert *函数之一,该类是GWTTestCase的祖先。 |
7 | assertTrue(boolean)函数断言传入的boolean参数的计算结果为true。 如果不是,则在JUnit中运行时测试将失败。 |
GWT - JUnit集成完整示例
此示例将指导您完成在GWT中显示JUnit Integration示例的简单步骤。
按照以下步骤更新我们在上面创建的GWT应用程序 -
步 | 描述 |
---|---|
1 | 使用导入现有项目向导(文件→导入→常规→现有项目到工作空间)在eclipse中使用名称HelloWorld导入项目。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是eclipse中的项目结构。
以下是修改后的模块描述符src/com.iowiki/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'/>
<!-- Inherit the UiBinder module. -->
<inherits name = "com.google.gwt.uibinder.UiBinder"/>
<!-- Specify the app entry point class. -->
<entry-point class = 'com.iowiki.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>
使用以下内容替换src/com.iowiki/client包中的HelloWorld.java的内容
package com.iowiki.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+"!";
}
}
使用以下内容替换test/com.iowiki/client包中的HelloWorldTest.java的内容
package com.iowiki.client;
import com.iowiki.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.iowiki.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));
}
}
}
使用生成的启动配置在Eclipse中运行测试用例。
我们将使用webAppCreator为开发模式和生产模式生成的启动配置在Eclipse中运行单元测试。
在开发模式下运行JUnit测试。
- 从Eclipse菜单栏中,选择Run→Run Configurations ...
- 在JUnit部分下,选择HelloWorldTest-dev
- 要将更改保存到参数,请按“应用”
- 要运行测试,请按“运行”
如果您的应用程序一切正常,这将产生以下结果 -
在生产模式下运行JUnit测试。
- 从Eclipse菜单栏中,选择Run→Run Configurations ...
- 在JUnit部分下,选择HelloWorldTest-prod
- 要将更改保存到参数,请按“应用”
- 要运行测试,请按“运行”
如果您的应用程序一切正常,这将产生以下结果 -
GWT - Debugging Application
GWT提供了调试客户端和服务器端代码的强大功能。
在开发模式期间,GWT Application基于Java代码,不会转换为JavaScript。
当应用程序在开发模式下运行时,Java虚拟机(JVM)实际上将应用程序代码作为编译的Java字节码执行,使用GWT功能连接到浏览器窗口。
GWT使用基于浏览器的插件连接到JVM。
因此,开发人员可以自由地使用任何基于Java的IDE来调试客户端GWT代码以及服务器端代码。
在本文中,我们将演示如何使用Eclipse调试GWT客户端代码。 我们将完成以下任务 -
- 在代码中设置断点并在BreakPoint Explorer中查看它们。
- 在调试期间逐行执行代码。
- 查看变量的值。
- 检查所有变量的值。
- 检查表达式的值。
- 显示悬挂线程的堆栈帧。
调试示例
此示例将指导您演示调试GWT应用程序的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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.iowiki.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主机文件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>Debugging Application Demonstration</h1>
<div id = "gwtContainer"></div>
</body>
</html>
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,我们将使用它来演示GWT Code的调试功能。
package com.iowiki.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+"!";
}
}
第1步 - 放置BreakPoints
在HelloWorld.java的onModuleLoad()的第一行放置一个断点
第2步 - 调试应用程序
现在点击 调试应用程序菜单并选择HelloWorld应用程序来调试应用程序。
如果一切正常,您必须在Eclipse中看到包含URL的GWT开发模式,如下所示。 双击URL以打开GWT应用程序。
一旦Application启动,您将看到关注Eclipse断点,因为我们已将断点放在入口点方法的第一行。
您可以看到挂起线程的堆栈跟踪。
您可以看到表达式的值。
您可以看到放置的断点列表。
现在继续按F6直到到达onModuleLoad()方法的最后一行。 作为功能键的参考,F6逐行检查代码,F5逐步进入内部,F8将恢复应用程序。 现在,您可以看到onModuleLoad()方法的所有变量的值列表。
可以使用与调试Java应用程序相同的方式调试GWT客户端代码。 将断点放在任何一行,并使用GWT的调试功能。
GWT - Internationalization
GWT提供了三种方式来实现GWT应用程序的国际化。我们将演示静态字符串国际化在项目中最常用的用法。
Sr.No. | 技术与描述 |
---|---|
1 | Static String Internationalization 这种技术最为普遍,在运行时只需要很少的开销; 是一种非常有效的翻译常量和参数化字符串的技术;最简单的实现。 静态字符串国际化使用标准Java属性文件来存储已翻译的字符串和参数化消息,并创建强类型的Java接口以检索其值。 |
2 | Dynamic String Internationalization 这种技术非常灵活,但比静态字符串国际化要慢。 主机页面包含本地化字符串,因此,当我们添加新的语言环境时,不需要重新编译应用程序。 如果要将GWT应用程序与现有服务器端本地化系统集成,则应使用此技术。 |
3 | Localizable Interface 这种技术是三种技术中最强大的。 实现Localizable允许我们创建自定义类型的本地化版本。 这是一种先进的国际化技术。 |
国际化GWT应用程序的工作流程
第1步:创建属性文件
创建包含要在应用程序中使用的消息的属性文件。 我们在示例中创建了一个HelloWorldMessages.properties文件。
enterName = Enter your name
clickMe = Click Me
applicationTitle = Application Internationalization Demonstration
greeting = Hello {0}
创建包含特定于语言环境的翻译值的属性文件。 我们在示例中创建了一个HelloWorldMessages_de.properties文件。 此文件包含德语翻译。 _de指定德语区域设置,我们将在我们的应用程序中支持德语。
如果要使用Eclipse创建属性文件,请将文件的编码更改为Other UTF-8 。选择该文件,然后在其中右键单击以打开其属性窗口。选择文本文件编码为Other UTF-8 。 应用并保存更改。
enterName = Geben Sie Ihren Namen
clickMe = Klick mich
applicationTitle = Anwendung Internationalisierung Demonstration
greeting = Hallo {0}
步骤2:将i18n模块添加到模块描述符XML文件
更新模块文件HelloWorld.gwt.xml以包含对德语语言环境的支持
<?xml version = "1.0" encoding = "UTF-8"?>
<module rename-to = 'helloworld'>
...
<extend-property name = "locale" values="de" />
...
</module>
第3步:创建等效于属性文件的接口
通过扩展GWT的Messages接口来创建HelloWorldMessages.java接口,以包括对内部化的支持。 它应包含与属性文件中的键相同的方法名称。 占位符将替换为String参数。
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);
}
第4步:在UI组件中使用消息接口。
在HelloWorldMessages中使用HelloWorld对象来获取消息。
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);
...
}
}
国际化 - 完整的例子
此示例将引导您完成演示GWT应用程序的国际化功能的简单步骤。
按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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.iowiki.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>
现在在src/com.iowiki/client包中创建HelloWorldMessages.properties文件并在其中放置以下内容
enterName = Enter your name
clickMe = Click Me
applicationTitle = Application Internationalization Demonstration
greeting = Hello {0}
现在在src/com.iowiki/client包中创建HelloWorldMessages_de.properties文件并在其中放置以下内容
enterName = Geben Sie Ihren Namen
clickMe = Klick mich
applicationTitle = Anwendung Internationalisierung Demonstration
greeting = Hallo {0}
现在在src/com.iowiki/client包中创建HelloWorldMessages.java类并将以下内容放入其中
package com.iowiki.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);
}
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,我们将使用它来演示GWT Code的国际化能力。
package com.iowiki.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 - 创建应用程序章节中那样在开发模式下编译和运行应用程序 。 如果您的应用程序一切正常,这将产生以下结果 -
现在更新URL以包含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的单页面应用程序,并且不包含大量页面,因此浏览器不会跟踪用户与Application的交互。 要使用浏览器的历史记录功能,应用程序应为每个可导航页面生成唯一的URL片段。
GWT提供History Mechanism来处理这种情况。
GWT使用一个术语token ,它只是一个应用程序可以解析为返回特定状态的字符串。 应用程序将此标记作为URL片段保存在浏览器的历史记录中。
例如,名为“pageIndex1”的历史记录将添加到URL,如下所示 -
http://www.iowiki.com/HelloWorld.html#pageIndex0
历史管理工作流程
第1步:启用历史记录支持
为了使用GWT History支持,我们必须首先将以下iframe嵌入到我们的主机HTML页面中。
<iframe src = "javascript:''"
id = "__gwt_historyFrame"
style = "width:0;height:0;border:0"></iframe>
第2步:将令牌添加到历史记录
以下示例统计信息如何将令牌添加到浏览器历史记录
int index = 0;
History.newItem("pageIndex" + index);
第3步:从历史记录中搜索令牌
当用户使用浏览器的后退/前进按钮时,我们将检索令牌并相应地更新我们的应用程序状态。
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);
}
}
});
现在让我们看看行动中的历史类。
历史课 - 完整的例子
此示例将指导您完成演示GWT应用程序的历史记录管理的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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.iowiki.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>
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,我们将使用它来演示GWT Code中的历史管理。
package com.iowiki.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使用History类支持浏览器历史记录管理,您可以参考GWT - History Class章节。
GWT使用一个术语token ,它只是一个应用程序可以解析为返回特定状态的字符串。 应用程序将此标记作为URL片段保存在浏览器的历史记录中。
在GWT - History Class章节中,我们通过编写代码来处理GWT - History Class的令牌创建和设置。
在本文中,我们将讨论一个特殊的小部件Hyperlink,它自动为我们完成令牌创建和历史管理,并提供书签的应用程序功能。
书签示例
此示例将指导您完成演示GWT应用程序的书签的简单步骤。
以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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.iowiki.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>
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,我们将使用它来演示GWT代码中的书签。
package com.iowiki.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.xml文件配置GWT日志记录。
我们可以配置启用/禁用日志记录; 我们可以启用/禁用特定处理程序,并更改默认日志记录级别。
记录器的类型
记录器以树结构组织,根记录器位于树的根部。
记录器的名称确定使用的父/子关系. 分隔名称的部分。
举个例子,如果我们有两个记录器Hospital.room1和Hospital.room2,那么他们就是兄弟姐妹,他们的父母是名为Hospital的记录器。 医院记录器(以及任何名称不包含点“。”的记录器)将根记录器作为父记录器。
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("");
日志处理程序
GWT提供默认处理程序,它将显示使用记录器创建的日志条目。
处理器 | 登录到 | 描述 |
---|---|---|
SystemLogHandler | stdout | 这些消息只能在DevMode窗口的开发模式中看到。 |
DevelopmentModeLogHandler | DevMode Window | 通过调用方法GWT.log进行日志记录。 这些消息只能在DevMode窗口的开发模式中看到。 |
ConsoleLogHandler | javascript控制台 | 登录到firebug Lite(适用于IE),Safari和Chrome使用的javascript控制台。 |
FirebugLogHandler | Firebug | 登录到firebug控制台。 |
PopupLogHandler | popup | 启用此处理程序时,记录位于应用程序左上角的弹出窗口。 |
SimpleRemoteLogHandler | server | 此处理程序将日志消息发送到服务器,使用服务器端日志记录机制记录它们。 |
配置GWT应用程序中的日志记录
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" />
使用记录器记录用户操作
/* Create Root Logger */
private static Logger rootLogger = Logger.getLogger("");
...
rootLogger.log(Level.SEVERE, "pageIndex selected: " + event.getValue());
...
记录框架示例
此示例将指导您完成演示GWT应用程序的日志记录功能的简单步骤。 按照以下步骤更新我们在GWT - Create Application的GWT应用程序GWT - Create Application章节 -
步 | 描述 |
---|---|
1 | 在com.iowiki包下创建一个名为HelloWorld的项目,如GWT - Create Application一章中所述。 |
2 | 修改HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html和HelloWorld.java ,如下所述。 保持其余文件不变。 |
3 | 编译并运行应用程序以验证实现的逻辑的结果。 |
以下是修改后的模块描述符src/com.iowiki/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'/>
<inherits name = "com.google.gwt.logging.Logging"/>
<!-- Specify the app entry point class. -->
<entry-point class = 'com.iowiki.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>
让我们有以下Java文件src/com.iowiki/HelloWorld.java ,我们将使用它来演示GWT代码中的书签。
package com.iowiki.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时,您可以看到显示pageIndex的日志正在打印。 检查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
现在更新模块描述符src/com.iowiki/HelloWorld.gwt.xml以启用popupHandler。
<?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.iowiki.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时,您可以看到日志正在打印,在弹出窗口中显示pageIndex。