dyerac |
|
|||
dyerac In Java |
公告
日歷
統(tǒng)計(jì)
導(dǎo)航常用鏈接留言簿(5)隨筆分類(49)
隨筆檔案(36)
文章分類(11)文章檔案(10)相冊(cè)dyerac搜索積分與排名
最新隨筆
最新評(píng)論
閱讀排行榜評(píng)論排行榜 |
原文出處:XML.comhttp://www.xml.com/pub/a/2006/07/12/google-web-toolkit-ajax-java-ant-xml.html
翻譯:劉嘉晗 http://www.aygfsteel.com/johnlau Google Web ToolkitBy Bruce Perry2006年7月12日 如果你是一名Java軟件或Ajax開(kāi)發(fā)者,可能Google Web Toolkit(GWT)已經(jīng)引起了你的注意。 2006年5月,Google發(fā)布了這一免費(fèi)的工具箱,遵循Apache風(fēng)格的許可證。GWT被設(shè)計(jì)用于以Java語(yǔ)言編寫(xiě)Ajax應(yīng)用。Google已經(jīng)提供了Windows和Linux下的beta版本,并承諾以后增加Mac OS X版本。 本文描述了在Max OS X上一個(gè)簡(jiǎn)單的Ajax應(yīng)用的開(kāi)發(fā),使用GWT和常用的Java工具,如Apache Ant,Tomcat 5.0 Servlet容器,以及IntelliJ IDEA集成開(kāi)發(fā)環(huán)境(后者是一款商業(yè)IDE)。本文假設(shè)讀者具有Java和Ant的基本知識(shí)。 結(jié)合使用Ant與GWT我下載了GWT Linux beta版本,用Java編寫(xiě)了我的應(yīng)用程序,然后用一個(gè)Ant構(gòu)建文件編譯和在一個(gè)Tomcat 5.0實(shí)例上部署了此程序。Ant文件執(zhí)行GWT Java-to-JavaScript編譯器。此“編譯器”是一個(gè)命令行腳本,它執(zhí)行一個(gè)GWT Java類,而后者為應(yīng)用程序輸出JavaScript腳本。 使用GWT beta包括兩種開(kāi)發(fā)模式:宿主(host)模式和web模式。 宿主模式是一個(gè)開(kāi)發(fā)中的中間步驟,它使用內(nèi)嵌的GWT瀏覽器;在這種模式下,已編譯代碼繼續(xù)在Java虛擬機(jī)(JVM)中運(yùn)行。然而,宿主模式對(duì)于我們這些借用Linux版本的Mac OS X用戶還不可用。Mac OS X下的宿主模式要等到Max OS X版本發(fā)布了。 一種不同的web開(kāi)發(fā)方式本文探討了GWT開(kāi)發(fā)者在為遠(yuǎn)程過(guò)程調(diào)用(RPC)創(chuàng)建服務(wù)時(shí)可能面對(duì)的一些典型的web開(kāi)發(fā)相關(guān)的任務(wù)。RPC是用于使用面向服務(wù)架構(gòu)(SOA)的應(yīng)用的軟件模型的一部分。這些開(kāi)發(fā)任務(wù)包括:
為您服務(wù)首先,我會(huì)簡(jiǎn)要描述該應(yīng)用程序創(chuàng)建的服務(wù)。它被設(shè)計(jì)用來(lái)展示GWT采用的模式。 該應(yīng)用程序在瀏覽器中顯示一個(gè)表單,要求用戶輸入名字,年齡,以及國(guó)家。當(dāng)用戶通過(guò)點(diǎn)擊按鈕提交表單時(shí),程序在一個(gè)文本區(qū)內(nèi)顯示一條服務(wù)器回應(yīng)而不需刷新頁(yè)面。圖1是程序在Safari瀏覽器中的顯示。 ![]() 圖1: GWT生成的一個(gè)簡(jiǎn)單視圖 例如,當(dāng)用戶在一個(gè)文本框?yàn)榭諘r(shí)點(diǎn)擊OK,Submit按鈕時(shí),結(jié)果如圖2所示。 ![]() 圖2: 應(yīng)用程序以紅色顯示一條錯(cuò)誤信息 巧妙的服務(wù)機(jī)制在Ajax應(yīng)用中使用RPC消除了顯式地處理XMLHttpRequest和相關(guān)聯(lián)的服務(wù)器返回值的需要,因?yàn)镚WT對(duì)象會(huì)為你處理這些通訊工作。 程序定義的每個(gè)服務(wù)需要兩個(gè)Java接口和一個(gè)Java類。為了編譯這些類,需要確定gwt-user.jar庫(kù)在classpath中(Ant文件中增加一個(gè)條目就可以解決)。以下代碼示范了定義我們的服務(wù)的Java接口。 package?com.parkerriver.gwt.testapp.client; import?com.google.gwt.user.client.rpc.RemoteService; public?interface?ShowRespService?extends?RemoteService{ ????String?displayResponse(String?req); } 服務(wù)接口必須擴(kuò)展GWT接口RemoteService。它只定義了一個(gè)方法 displayResponse()。 你還需要定義一個(gè)接口,客戶端或最終被下載的JavaScript代碼將會(huì)用它調(diào)用服務(wù)方法。GWT使用了一種回調(diào)設(shè)計(jì)模式,當(dāng)我給出客戶端代碼的時(shí)候會(huì)再來(lái)描述它(請(qǐng)看MyForm.java)。 package?com.parkerriver.gwt.testapp.client; import?com.google.gwt.user.client.rpc.AsyncCallback; public?interface?ShowRespServiceAsync?{ ????public?void?displayResponse(String?s, ????????????????????????????????AsyncCallback?callback); } 要使一個(gè)服務(wù)在GWT中可用必須遵守命名約定;在服務(wù)接口名(ShowRespService)后增加Async后綴。AsyncCallback對(duì)象是GWT API的一部分,它的目的是為客戶端處理服務(wù)響應(yīng)。不管怎樣,等你看了這段代碼應(yīng)用的地方后會(huì)對(duì)這一行為有更清晰的了解。這些對(duì)象定義都位于用于生成客戶端JavaScript的Java代碼中。 一個(gè)改頭換面的servlet最后,你需要定義一個(gè)Java類來(lái)實(shí)現(xiàn)遠(yuǎn)程服務(wù)接口。這個(gè)類將會(huì)存在于你的Ajax應(yīng)用程序的服務(wù)器端。 package?com.parkerriver.gwt.testapp.server; import?com.parkerriver.gwt.testapp.client.ShowRespService; import?com.google.gwt.user.server.rpc.RemoteServiceServlet; import?java.util.Date; public?class?ShowRespServiceImpl?extends?RemoteServiceServlet ????????implements?ShowRespService??{ ????public?String?displayResponse(String?req)?{ ????????if(req.length()?<?1)?{ ????????????throw?new?IllegalArgumentException( ????????????????????"Blank?submissions?from?the?client?are?invalid."); ????????} ????????StringBuffer?buf?=?new?StringBuffer("Your?submission:?"); ????????Date?date?=?new?Date(); ????????String?serverInfo?=?this.getServletContext().getServerInfo(); ????????buf.append(req); ????????buf.append("\n"); ????????buf.append("Server?response:?"); ????????buf.append(date.toString()); ????????buf.append("\n"); ????????buf.append(serverInfo); ????????return?buf.toString(); ????} } 該類必須擴(kuò)展RemoteServiceServlet,這是一個(gè)GWT API對(duì)象,它本身擴(kuò)展了javax.servlet.http.HttpServlet。也就是說(shuō),該類和它實(shí)現(xiàn)的接口需要被部署到你的servlet容器。 步驟現(xiàn)在我們已經(jīng)定義了服務(wù),讓我們退回幾分鐘來(lái)看一看程序的目錄結(jié)構(gòu)。Google Web Toolkit包括了一個(gè)名為applicationCreator的命令行腳本,它將會(huì)為你生成項(xiàng)目目錄結(jié)構(gòu)。解壓縮GWT下載包后,你可以在頂層目錄中找到applicationCreator。我使用下面的命令行來(lái)開(kāi)始: applicationCreator?-out?/Users/bruceperry/1gwt/secondapp/?com.parkerriver.gwt.testapp.client.MyForm 圖3顯示了目錄結(jié)構(gòu) ![]() 圖3: 一個(gè)GWT和IntelliJ項(xiàng)目目錄 applicationCreator生成./src目錄和MyForm-compile以及MyForm-shell腳本。我的Ant文件執(zhí)行MyForm-compile;另一個(gè)腳本運(yùn)行宿主模式。./src目錄包括與最初的包命名相符的嵌套目錄結(jié)構(gòu),如圖4所示。 ![]() 圖4:一個(gè)GWT應(yīng)用程序的包和模塊 文件MyForm.gwt.xml是生成的配置文件,GWT稱之為“模塊(module)”。它為你的程序定義了表示“入口點(diǎn)(entry point)”的Java類,類似于包含main()方法的Java類。 <module> ????<!--Inherit?the?core?Web?Toolkit?stuff.??????????????????--> ????<inherits?name="com.google.gwt.user.User"/> ????<!--Specify?the?app?entry?point?class.???????????????????--> ????<entry-point?class="com.parkerriver.gwt.testapp.client.MyForm"/> </module> 其它的文件或目錄是IntelliJ Web application project的產(chǎn)物,包括./classes,./WEB-INF,和./gwtproj.ipr,所以不需要特別留意它們。 另外,./www目錄之前并不會(huì)出現(xiàn)(除非你自己創(chuàng)建它),直到運(yùn)行GWT編譯器生成程序代碼。我的項(xiàng)目使用Ant文件getproj.xml,而項(xiàng)目屬性在gwtproj.properties中定義。在我展示Ant構(gòu)建文件之前,我們先看一下代表程序入口點(diǎn)的MyForm.java類。 入口點(diǎn)MyForm.jaca類實(shí)現(xiàn)了GWT API接口EntryPoint。所以,該類必須實(shí)現(xiàn)onModuleLoad()方法,當(dāng)瀏覽器載入你的Ajax程序時(shí),瀏覽器的JavaScript引擎將會(huì)調(diào)用它。 換句話說(shuō),GWT編譯器將這個(gè)類編譯為JavaScript代碼。MyForm.java類為瀏覽器視圖建立表單控件。該類同時(shí)決定了用戶點(diǎn)擊OK,Submit按鈕時(shí)的響應(yīng)。代碼中的注釋詳細(xì)描述了到底發(fā)生了什么,所以我在正文中不再贅述。 package?com.parkerriver.gwt.testapp.client; import?com.google.gwt.core.client.EntryPoint; import?com.google.gwt.core.client.GWT; import?com.google.gwt.user.client.DOM; import?com.google.gwt.user.client.Window; import?com.google.gwt.user.client.Element; import?com.google.gwt.user.client.rpc.ServiceDefTarget; import?com.google.gwt.user.client.rpc.AsyncCallback; import?com.google.gwt.user.client.ui.*; import?java.util.Iterator; public?class?MyForm?implements?EntryPoint?{ ????//提供狀態(tài)信息的HTML div元素的id ??? private?String?statusId?=?"status"; ????//一個(gè)Grid對(duì)象;實(shí)際上,是一個(gè)HTML table ????private?Grid?grid?=?new?Grid(5,?2); ????//其它用戶界面對(duì)象 ????private?Label??nmLab?=?new?Label(); ????private?Label??ageLab?=?new?Label(); ????private?Label??homeLab?=?new?Label(); ????private?TextBox?nmTxt?=?new?TextBox(); ????private?TextBox?ageTxt?=?new?TextBox(); ????private?TextBox?homeTxt?=?new?TextBox(); ????private?Button?okBut?=?new?Button(); ????private?TextArea?tarea?=?new?TextArea(); ????/* 當(dāng)瀏覽器載入應(yīng)用程序時(shí)本方法被調(diào)用。 ??????? 本方法設(shè)置3個(gè)標(biāo)簽和文本框,以及一個(gè) ??????? 按鈕和用來(lái)顯示服務(wù)器相應(yīng)的文本區(qū)*/ ?????public?void?onModuleLoad()?{ ????????//設(shè)置標(biāo)簽和文本域 ????????nmLab.setText("Full?Name:"); ????????nmTxt.setMaxLength(25); ????????ageLab.setText("Age:"); ????????ageTxt.setVisibleLength(3); ????????ageTxt.setMaxLength(3); ????????homeLab.setText("Home?country:"); ????????homeTxt.setMaxLength(25); ????????//將這些控件放入Grid中 ????????grid.setWidget(0,0,nmLab); ????????grid.setWidget(0,1,nmTxt); ????????grid.setWidget(1,0,ageLab); ????????grid.setWidget(1,1,ageTxt); ????????grid.setWidget(2,0,homeLab); ????????grid.setWidget(2,1,homeTxt); ????????//設(shè)置按鈕和文本區(qū) ????????tarea.setCharacterWidth(40); ????????tarea.setVisibleLines(25); ????????okBut.setText("OK,?Submit"); ????????//通過(guò)增加一個(gè)listener對(duì)象為按鈕設(shè)置行為 ????????//詳細(xì)地講,一個(gè)帶有onClick()事件處理器的 ????????//ClickListener對(duì)象。 ????????okBut.addClickListener(new?ClickListener()?{ ????????????public?void?onClick(Widget?sender)?{ ????????????????//提示用戶遠(yuǎn)程過(guò)程調(diào)用的狀態(tài); ????????????????//見(jiàn)下面的方法 ????????????????showRpcStatus(true); ????????????????//為服務(wù)器端服務(wù)創(chuàng)建一個(gè)客戶端存根的實(shí)例 ??????????????? ShowRespServiceAsync?respService?= ????????????????????????(ShowRespServiceAsync)?GWT ????????????????????????????????.create(ShowRespService.class); ????????????????ServiceDefTarget?endpoint?=?(ServiceDefTarget)?respService; ????????????????//我們的服務(wù)的實(shí)現(xiàn)是一個(gè)RemoteServiceServlet的實(shí)例, ????????????????//所以提供到該servlet的服務(wù)器路徑 ????????????????//該路徑為web.xml中設(shè)置的值 ????????????????endpoint.setServiceEntryPoint("/parkerriver/s/showresp"); ????????????????//該接口處理服務(wù)器響應(yīng)。 ????????????????//它會(huì)在一個(gè)文本區(qū)中顯示服務(wù)器的響應(yīng)。 ????????????????//如果回復(fù)消息表示一個(gè)錯(cuò)誤 ????????????????//則將用紅色字體顯示 ????????????????AsyncCallback?callback?=?new?AsyncCallback()?{ ????????????????????public?void?onSuccess(Object?result)?{ ????????????????????????//如有,則移除與錯(cuò)誤消息外觀相關(guān)的‘warning’CSS樣式 ????????????????????????// ????????????????????????if(tarea.getStyleName(). ????????????????????????????????equalsIgnoreCase("warning")){ ????????????????????????????tarea.removeStyleName("warning"); ????????????????????????} ????????????????????????//文本區(qū)顯示服務(wù)器的返回值 ????????????????????????tarea.setText((String)result); ????????????????????} ????????????????????public?void?onFailure(Throwable?caught)?{ ????????????????????????//文本區(qū)顯示任何異常消息 ????????????????????????tarea.setStyleName("warning"); ????????????????????????tarea.setText( ????????????????????????????"Server?request?raised?an?error;?Java?exception?:?"+ ????????????????????????????caught?==?null???"An?unknown?exception"?: ????????????????????????????????????????caught.getMessage()); ????????????????????} ????????????????}; ????????????????//調(diào)用服務(wù)方法。 ????????????????//首先驗(yàn)證表單值。 ????????????????try{ ????????????????????respService.displayResponse( ????????????????????????????getPanelTextContent(grid,true), ????????????????????????????callback); ????????????????}?catch?(Exception?e)?{ ????????????????????tarea.setStyleName("warning"); ????????????????????tarea.setText("Server?request?raised?an?error:?"+ ????????????????????????????e.getMessage()); ????????????????}??finally?{ ????????????????????//當(dāng)我們完成RPC調(diào)用時(shí) ????????????????????//移除狀態(tài)信息 ????????????????????showRpcStatus(false); ????????????????} ????????????} ????????}); ????????//現(xiàn)在將這些控件加到Grid上 ????????grid.setWidget(3,0,okBut); ????????grid.setWidget(3,1,tarea); ????????//為OK按鈕的單元設(shè)定垂直對(duì)齊屬性 ????????grid.getCellFormatter().setVerticalAlignment(3,0, ????????????????HasVerticalAlignment.ALIGN_TOP); ????????//為文本框設(shè)置垂直對(duì)齊屬性, ????????//以使它們合適地排列 ????????grid.getCellFormatter().setVerticalAlignment(0,1, ????????????????HasVerticalAlignment.ALIGN_BOTTOM); ????????grid.getCellFormatter().setVerticalAlignment(1,1, ????????????????HasVerticalAlignment.ALIGN_BOTTOM); ????????grid.getCellFormatter().setVerticalAlignment(2,1, ????????????????HasVerticalAlignment.ALIGN_BOTTOM); ????????//將grid,實(shí)際上是一個(gè)HTML table,加到 ????????//瀏覽器HTML中id值為"gridholder"的div元素中。 ????????RootPanel.get("gridholder").add(grid); ????} ????/*簡(jiǎn)單地測(cè)試是否有為空的域,然后以單一字符串返回 ??? ?? 提交的值。 ??? ?? HasWidgets是Grid和其它panel類型的對(duì)象實(shí)現(xiàn)的一個(gè)接口。 ??? ?? 因此,我們可以將grid傳入該方法;遍歷它包含的文本框, ??? ?? 并且驗(yàn)證文本框的內(nèi)容。 ????*/ ????private?String?getPanelTextContent(HasWidgets?panelType, ???????????????????????????????????????boolean?validateContent)?{ ????????StringBuffer?buf?=?new?StringBuffer(""); ????????String?tmp?=?null; ????????if(panelType?!=?null)?{ ???????????//為了簡(jiǎn)介,省略 ![]() ????????} ????????//返回以空格分隔的文本框的內(nèi)容 ??????? return?buf.toString(); ????} ???? ????/* 過(guò)于簡(jiǎn)化的驗(yàn)證!?*/ ????private?boolean?validateText(String?_content){ ????????return?_content.length()?>?0; ????} ????private?int?getTextboxCount(HasWidgets?pType){ ????????//未顯示: 返回panel中TextBox控件的數(shù)量 ??????? ????} ????/* 如果響應(yīng)很長(zhǎng)時(shí)間才到達(dá) ???? 則顯示給用戶一個(gè)狀態(tài)信息。*/ ????private?void?showRpcStatus(boolean?_on){ ????????//利用GWT DOM API進(jìn)行JavaScript DOM編程 ?????? ????????Element?el?=?DOM.getElementById(statusId); ????????if(el?!=?null)??{ ????????????if(_on)?{ ????????????????DOM.setStyleAttribute(el,"font-size","1.2em"); ????????????????DOM.setStyleAttribute(el,"color","green"); ????????????????DOM.setInnerHTML(el,?"Fetching?server?info ![]() ????????????}??else{ ????????????????DOM.setInnerHTML(el,?""); ????????????} ????????} ????} } 代碼中大多部分處理GWT API。值得一提的是如果你需要實(shí)現(xiàn)JavaScript DOM編程,如showRpcStatus()方法中那樣,你可以通過(guò)使用com.google.gwt.user.client.DOM類實(shí)現(xiàn)這個(gè)任務(wù)。 構(gòu)建文件以下是Ant構(gòu)建文件的重點(diǎn);它:
負(fù)責(zé)編譯Java類和執(zhí)行到JavaScript的轉(zhuǎn)換的兩個(gè)Ant任務(wù)定義為如果產(chǎn)生任何錯(cuò)誤,則使整個(gè)構(gòu)建失敗。 Ant XML這里是gwtproj.properties文件包含的部分內(nèi)容: web.deploy.location=/users/bruceperry/parkerriver/gwt web.classes.location=/users/bruceperry/parkerriver/WEB-INF/classes 下面的XML表示了上述Ant文件的主要內(nèi)容;完整文件的鏈接在本文的資源一節(jié)中。 <?xml?version="1.0"?encoding="UTF-8"?> <project?name="gwtproj"?default="all"> ????<property?file="gwtproj.properties"/> ???? ?????<!--?The?top-level?directory?for?the?project?and ????where?the?ant?file?resides?--> ????<dirname?property="module.gwtproj.basedir"?file="${ant.file}"/> ???? ?????<!--?The?./classes?directory?inside?the?top-level?directory?--> ?????<property?name="gwtproj.output.dir"?value= ????????????"${module.gwtproj.basedir}/classes"/> ???????????? ????<!--?This?target?calls?MyForm-compile?to?create ????all?the?content?in?the?./www?directory?--> ????<target?name="gwt-compile"?depends= ????????????"compile.production.classes" ????????????description="use?gwt's?compiler"> ????????<delete> ????????????<fileset?dir="${web.deploy.location}"?includes="**/*"/> ????????</delete> ????????<exec?executable= ????????????????"${module.gwtproj.basedir}/MyForm-compile" ??????????????failonerror="true"/> ????????<copy?todir="${web.deploy.location}"> ????????????<fileset?dir= ????????????????????"${module.gwtproj.basedir}/www"> ????????????</fileset> ????????</copy> ????</target> ????<target?name="compile.production.classes"?description= ????????????"Compile?the?gwtproj?production?classes"> ????????<mkdir?dir="${gwtproj.output.dir}"/> ????????<javac?destdir="${gwtproj.output.dir}"?debug= ????????????????"on"?failonerror="true"?nowarn= ????????????????"off"?memoryMaximumSize="128m"?fork= ????????????????"true"?executable="${module.jdk.home.gwtproj}/bin/javac"> ????????????<classpath?refid="gwtproj.module.classpath"/> ????????????<src?refid="gwtproj.module.sourcepath"/> ????????</javac> ????</target> ???? ??<!--?copy?the?Java?servlet?classes?to?the?web?application?--> ????<target?name="deploy.classes"??depends="gwt-compile" ????????????description="copy?classes?to?web?directory"> ????????<copy?todir="${web.classes.location}"> ????????????<fileset?dir="${gwtproj.output.dir}"> ????????????</fileset> ????????</copy> ????</target> ???? ????<target?name="all"?depends="deploy.classes" ????????????description="build?all"/> </project> 你可以在IDE中運(yùn)行該Ant文件(比如在IntelliJ中)或者在包含構(gòu)建文件的目錄中運(yùn)行下面的命令行: ant?-buildfile?gwtproj.xml 大多數(shù)情況下,在更改應(yīng)用程序并運(yùn)行Ant后,你可以通過(guò)在瀏覽器中刷新頁(yè)面看到所作的改變。 最后設(shè)置在最后的設(shè)置上,你可能需要了解的是添加gwt-user.jar庫(kù)到你的web應(yīng)用的/WEB-INF/lib目錄。 我創(chuàng)建了我自己的JAR文件,去掉了其中的javax包,命名為gwt-user-deploy.jar,并添加到/WEB-INF/lib。這是因?yàn)門omcat將不會(huì)載入web應(yīng)用程序中包含servlet API類的庫(kù)。 web開(kāi)發(fā)者的吹毛求疵applicationCreator同時(shí)創(chuàng)建了你的Ajax應(yīng)用程序的HTML前端,本例中名為MyForm.html。 如果你的應(yīng)用程序的HTML需要遵從如XHTML transitional或Strict時(shí)怎么辦呢?對(duì)于XHTML transitional的情況,我首先在MyForm.html頂端增加了所需的DOCTYPE,以及html標(biāo)簽的相關(guān)屬性: <!DOCTYPE?html?PUBLIC?"-//W3C//DTD?XHTML?1.0?Transitional//EN" ????????"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd"> <html?xmlns="http://www.w3.org/1999/xhtml"?xml:lang="en"?lang="en"> 然后我上傳MyForm.html到http://validator.w3.org/的World Wide Web協(xié)會(huì)的HTML驗(yàn)證器。 運(yùn)行驗(yàn)證器后,我對(duì)HTML做了一些簡(jiǎn)單的修改,如合適地關(guān)閉元標(biāo)簽以及增加type="text/javascript"到script標(biāo)簽。 Strict:嘖嘖然而,如果你要遵從XHTML Strict標(biāo)準(zhǔn),則可能需要做一些更復(fù)雜的更改。例如,W3C的驗(yàn)證器將iframe標(biāo)簽標(biāo)為“undefined element”,iframe是GWT的歷史支持所需要的(提供如瀏覽器的后退按鈕同樣的功能)。XHTML已經(jīng)移除了iframe元素。 這對(duì)你可能不是一個(gè)問(wèn)題(可能會(huì)同其它明顯問(wèn)題一起在GWT的未來(lái)版本中解決);但是,你可以自己實(shí)現(xiàn)替代策略,如擴(kuò)展GWT的類和創(chuàng)建你自己的兼容的控件。 使控件各就各位視覺(jué)外觀設(shè)計(jì)是web開(kāi)發(fā)中總是出現(xiàn)的問(wèn)題。項(xiàng)目設(shè)計(jì)者希望頁(yè)面看起來(lái)和他們?cè)贏dobe Illustrator中創(chuàng)建的一摸一樣,是嗎? 盡管在復(fù)雜的Ajax項(xiàng)目中你可能無(wú)法實(shí)現(xiàn)這一使程序養(yǎng)眼的理想,至少你可以使用Firefox的DOM Inspector來(lái)檢視你的Java類最終生成的HTML。那么從這里開(kāi)始。 打開(kāi)Firefox的Tools=>DOM Inspector菜單項(xiàng)(如圖5) ![]() 圖5: 用DOM Inspector查看HTML 可見(jiàn)Java代碼中的com.google.gwt.user.client.ui.Grid對(duì)象實(shí)現(xiàn)為一個(gè)HTML table標(biāo)簽。table中包含OK,Submit按鈕的TD標(biāo)簽與一個(gè)樣式屬性“verticle-align:top”關(guān)聯(lián)。 這使按鈕與文本區(qū)頂端對(duì)齊。下面是MyForm.java類中設(shè)置對(duì)齊方式的代碼: //set?the?vertical?alignment?for?the?OK?button's?cell ????????grid.getCellFormatter().setVerticalAlignment(3,0, ????????????????HasVerticalAlignment.ALIGN_TOP); 如果代碼中沒(méi)有此調(diào)用,按鈕就會(huì)很業(yè)余地掛在文本區(qū)的中間區(qū)域。 現(xiàn)在要做的只是使按鈕與它上面的文本標(biāo)簽左對(duì)齊。 資源?? ?Google Web Toolkit: http://code.google.com/webtoolkit/??? 本文代碼: gwtarticle_jul06.zip XML.com Copyright?? 1998-2006 O'Reilly Media, Inc.
|
![]() |
|
Copyright © dyerac in java... | Powered by: 博客園 模板提供:滬江博客 |