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>
