window , 就像HTML的 DIV 标签, 用于为组件分组。不同于其它的组件, window 有如下的特点。
window是一个ID空间的所有者。window可以包含任意组件, 包括其自身。如果通过标识指定,可以使用getFellow
方法来找到它。
window 可以被重叠,弹出和嵌入(overlapped, popup, and embedded)。
window 可以是对话框(modal dialog)。
window可以有一个title,一个caption 和 一个 border。标题(title) 是 title
属性指定的。 标题 (caption)是 caption
组件声明的。 caption
组件的所有子组件都会出现在 title 的右边。
<window title="Demo" border="normal" width="350px"> <caption> <toolbarbutton label="More"/> <toolbarbutton label="Help"/> </caption> <toolbar> <toolbarbutton label="Save"/> <toolbarbutton label="Cancel"/> </toolbar> What is your favorite framework? <radiogroup> <radio label="ZK"/> <radio label="JSF"/> </radiogroup> </window>
你可以为caption 指定标签和图像,其外观如下。
<window id="win" title="Main" border="normal" width="200px"> <caption image="/img/coffee.gif" label="Hi there!"/> <checkbox label="Hello, World!"/> </window>
若将closable
属性值设为true,close 按钮会显示在window 组件中,这样可以关闭此window 。一旦用户点击了close按钮,onClose事件会被送到window。这样此事件会被window的onClose
方法处理。那么,onClose
在默认情况下会把 window 自身移除。
你也可以重定义此方法,使其做你想做的事情。或者,注册一个监听器来改变默认的行为。例如,你可以选择隐藏而不是关闭。
<window closable="true" title="Detach on Close" border="normal" width="200px" onClose="self.visible = false; event.stopPropagation();"> In this example, this window hides itself when the close button is clicked. </window>
注意,必须调用event.stopPropagation
()阻止Window.onClose()被调用。
提示: 若为一弹出window,当由于用户点击window的外围或按下ESC键关闭此弹出window
时, onOpen
事件(open=false) 会被送至 window 。
这会有些困惑,但是onClose
被送至服务器来询问移除还是隐藏window。默认情况下,window会被移除。当然,应用程序可以重定义此方法并且让其做任何事情,就像上面描述的一样。
另外,onOpen
是一个通知(notification)。此事件被送出以通知应用程序客户端已经隐藏了window 。应用程序并不能阻止window被隐藏,或改变被移除的行为。
如果你允许用户重定义window的大小,可以将sizable
属性设为true
。这样用户可以拖曳边框来改变
window
的尺寸。
<window id="win" title="Sizable Window" border="normal" width="200px" sizable="true"> This is a sizable window. <button label="Change Sizable" onClick="win.sizable = !win.sizable"/> </window>
Zk的window支持四种样式类:embedded
,
overlapped
,
popup
和 wndcyan
。当然,你可以添加更多。
默认情况下,sclass
属性与 window 模式是一样的,所以不同模式window 的外观是不同的。要想改变外观,可以按下例描述的那样简单的为 sclass
属性指定一个值。
<hbox> <window title="Embedded Style" border="normal" width="200px"> Hello, Embedded! </window> <window title="Cyan Style" sclass="wndcyan" border="normal" width="200px"> Hello, Cyan! </window> <window title="Popup Style" sclass="popup" border="normal" width="200px"> Hello, Popup! </window> <window title="Modal Style" sclass="modal" border="normal" width="200px"> Hello, Modal! </window> </hbox>
通过指定contentStyle
属性可以改变window中内容块的亲自体会(look and feel)。
<window title="My Window" border="normal" width="200px" contentStyle="background:yellow"> Hello, World! </window>
border
属性是否显示window 的边框。默认的样式仅支持normal
和 none
。默认为none
。
当然,你可以提供额外的样式类(style class)。例如,
<zk> <style> div.wc-embedded-dash { padding: 2px; border: 3px dashed #aab; } </style> <window title="My Window" border="dash" width="200px"> Hello, World! </window> </zk>
wc-embedded-dash
定义了window 内框(inner box)的样式。样式类通过连锁(concatenating)wc
[37]命名,sclass
属性和border属性是一起的,并且以横线(-)分开它们。在此例中,由于此窗口是嵌入式的(embedded),所以为sclass
为embedded
,而且没有明确的sclass
被指定(所以使用了默认的sclass
)。
window有四种模式:重叠,弹出,Modal,标示和嵌入。嵌入为默认模式。可以使用doOverlapped
,
doPopup
,
doModal
,
doHighlighted
和 doEmbedded
方法来改变模式。如下,
<zk> <window id="win" title="Hi!" border="normal" width="200px"> <caption> <toolbarbutton label="Close" onClick="win.setVisible(false)"/> </caption> <checkbox label="Hello, Wolrd!"/> </window> <button label="Overlap" onClick="win.doOverlapped();"/> <button label="Popup" onClick="win.doPopup();"/> <button label="Modal" onClick="win.doModal();"/> <button label="Embed" onClick="win.doEmbedded();"/> <button label="Highlighted" onClick="win.doHighlighed();"/> </zk>
重叠window 和其它组件是重叠的,这样用户可以到处拖曳此window,并且开发人员可以使用setLeft
和setTop
方法来设置其位置。
除了doOverlapped
,你也可以按如下方式使用mode
属性,
<window title="My Overlapped" width="300px" mode="overlapped"> </window>
modal window (亦称对话框,modal dialog)与重叠window 类似,除了modal window可以挂起执行,直到endModal
, doEmbedded
, doOverlapped
, doHighlighted
, 和 doPopup
方法中的一个被调用。
除了挂起执行,modal window还可以使不属于其的组件失效。
modal window会自动位于浏览器的中央,你可以控制它的位置。
标示window 与重叠window 类似,除了标示window 的视觉效果与modal window相同。换言之,标示window 位于浏览器的中央,并且使不属于其的组件失效。
但是,标示window 不会挂起执行。就像重叠window,一旦模式改变,执行会继续。例如,仅当win1被关闭后f1()才会被调用,而在win2变为标示后g()被立即调用。
win1.doModal(); //the execution is suspended until win1 is closed f1(); win2.doHighlighted(); //the execution won't be suspended g1()
如果你不喜欢挂起事件处理线程,可以使用标示window 代替modal window。参考特性提示一章中使用Servlet线程处理事件的一节。
不同于其它的模式,你仅能在事件监听器中将window 放置在modal模式中。换言之,你可以在事件监听器中调用doModal
()或 setMode
("modal
")。
<zk> <window id="wnd" title="My Modal" visible="false" width="300px"> <button label="close" onClick="wnd.visible = false"/> </window> <button label="do it" onClick="wnd.doModal()"/> </zk>
另外,如果在组件创建阶段(Component Creation Phase)[38] 执行,下面的例子是错误的。
//t1.zul <window title="My Modal" width="300px" closable="true" mode="modal"> </window>
如果在浏览器中直接打开,将会导致如下结果[39] 。
下面的代码会导致相同的结果。
//t2.zul <window title="My Modal" width="300px" closable="true"> <zscript> self.doModal(); </zscript> </window>
如果你需要在页面加载时创建一个modal window,可以按如下方式提交onModal
事件。
//t3.zul <window title="My Modal" width="300px" closable="true"> <zscript> Events.postEvent("onModal", self, null); </zscript> </window>
注: 下面的代码会正确执行,甚至t1
.zul
将window直接设置为modal模式(就像上面一样)。为什么呢?它在一个事件监听器中执行(onClick
)。
<button label="do it"> <attribute name="onClick"> Executions.createComponents("t1.zul", null, null); //it loads t1.zul in this event listener for onClick </attribute> </button>
除了left
和top
属性,你可以使用position
属性来控制重叠/弹出/modal window 的位置。例如,下面的代码片断将window置于右下角。
<window width="300px" mode="overlapped" position="right,bottom"> ...
position
属性可以是下列常量的集合,各常量之间以逗号 (,)隔开。
常量 |
描述 |
---|---|
|
将winow组件放置在中间。若制定了
|
|
将winow组件在左边。 left属性被忽略。 |
|
将winow组件在右边。
|
|
将winow组件在顶部。
|
|
将winow组件在底部。
|
默认情况下,其值为null。也就是,重叠和弹出window 的位置由left
和top
决定,而modal window居中。
XUL组件集支持下列通用对话框来简化一些通用任务。
org.zkoss.zul.Messagebox
类提供了一套功能来显示消息框。典型应用是当发生错误时警告用户,或促使用户作出决定。
if (Messagebox.show("Remove this file?", "Remove?", Messagebox.YES | Messagebox.NO, Messagebox.QUESTION) == Messagebox.YES) { ...//remove the file }
由于警告用户有误是很平常的,所以一个称为alert
的全局函数被加进了zscript。alert
函数是Messagebox
类中show
方法的一个捷径。换言之,下列两条语句是等价的。
alert("Wrong"); Messagebox.show("Wrong");
注意Messagebox
为一个modal window,所以它也受相同的约束:仅在事件监听器中是可执行的。因此,下列代码将会失败。参考上面的Modal窗口和事件监听器一节获取更多的描述。
<window title="Messagebox not allowed in paging loading"> <zscript> //failed since show cannot be called in paging loading if (Messagebox.show("Redirect?", "Redirect?", Messagebox.YES | Messagebox.NO, Messagebox.QUESTION) == Messagebox.YES) Executions.sendRedirect("another.zul"); </zscript> </window>
org.zkoss.zul.Fileupload
类提供了一套功能用以帮助用户向服务器上传文件。一旦调用了get方法,浏览器端会显示一个文件上传对话框来促使用户指定要上传的文件。直到用户已经上传了文件或点击了放弃按钮其才会返回。
<window title="Fileupload Demo" border="normal"> <image id="image"/> <button label="Upload"> <attribute name="onClick">{ Object media = Fileupload.get(); if (media instanceof org.zkoss.image.Image) image.setContent(media); else if (media != null) Messagebox.show("Not an image: "+media, "Error", Messagebox.OK, Messagebox.ERROR); }</attribute> </button> </window>
如果你允许一次上传多个文件,可以按如下方式指定允许数字的最大值。
<window title="fileupload demo" border="normal"> <button label="Upload"> <attribute name="onClick"><![CDATA[{ Object media = Fileupload.get(5); if (media != null) for (int j = 0; j < media.length; ++j) { if (media[j] instanceof org.zkoss.image.Image) { Image image = new Image(); image.setContent(media[j]); image.setParent(pics); } else if (media[j] != null) { Messagebox.show("Not an image: "+media[j], "Error", Messagebox.OK, Messagebox.ERROR); } } }]]></attribute> </button> <vbox id="pics"/> </window>
fileupload不是一个modal对话框。它是一个组件,所以fileupload可以和其它组件一起插入文字之间。
注:除了静态的get
方法用于打开文件上传对话框,org.zkoss.zul.Fileupload
本身即为一个组件。 即所谓的fileuplod
组件。
例如,
<image id="img"/> Upload your hot shot: <fileupload onUpload="img.setContent(event.media)"/>
当按下上传按钮后,onUpload
事件及org.zkoss.zk.ui.event.UploadEvent
事件的一个实例被送出。你可以使用getMedia
或 getMedias
方法获取上传文件的内容。
注意getMedia
和 getMedias
方法返回null即表示没有文件被指定但上传按钮被按下了。
org.zkoss.zul.Filedownload
类提供了一套功能用以帮助用户从服务器下载文件。不同于iframe
组件在浏览器窗口显示文件,如果其中的一个save
方法被调用,则文件下载对话框会显示在浏览器端。然后,用户可以指定在本地文件系统中的存储路径。
<button label="Download download.html"> <attribute name="onClick">{ java.io.InputStream is = desktop.getWebApp().getResourceAsStream("/test/download.html"); if (is != null) Filedownload.save(is, "text/html", "download.html"); else alert("/test/download.html not found"); }</attribute></button>