ZK允许用户在用户界面内拖曳特定的组件。例如,将文件拖至其它的目录,或将商品拖至购物车。
若一个组件可以被拖曳则它是可拖曳的。若用户可以将一个可拖曳的组件放入到某一组件内,则称该组件是可放下的(droppable)。
注: 在放下后,ZK并不假定关于发生什么的任何行为。这由应用程序开发人员编写onDrop事件监听器来决定。
如果应用程序什么也不做,被拖曳的组件只是简单的移回它的初始位置.
使用ZK,通过指派draggable属性除了"false"外的任何值,你可以使一个组件变为可拖曳的。若想禁用,则将其设为"false"。
<image draggable="true"/>
类似的,可以将droppable属性赋值为"true"来将一个组件变为可放下的。
<hbox droppable="true"/>
然后,用户可以拖曳一个可拖曳的组件,并将其放入一个可放下的组件。
一旦用户拖曳一个组件并将其放入可放下的另一个组件,onDrop事件会通知用户放入组件的组件。onDrop事件是org.zkoss.ui.event.DropEvent的一个实例。调用getDragged方法,你可以获取什么被拖曳(及放下)了。
注意 onDrop事件的目标是可放下的组件,而不是被拖曳的组件。
下面是一个简单的例子,允许用户使用拖放对列表项目重新排序。

<window title="Reorder by Drag-and-Drop" border="normal">
Unique Visitors of ZK:
<listbox id="src" multiple="true" width="300px">
<listhead>
<listheader label="Country/Area"/>
<listheader align="right" label="Visits"/>
<listheader align="right" label="%"/>
</listhead>
<listitem draggable="true" droppable="true" onDrop="move(event.dragged)">
<listcell label="United States"/>
<listcell label="5,093"/>
<listcell label="19.39%"/>
</listitem>
<listitem draggable="true" droppable="true" onDrop="move(event.dragged)">
<listcell label="China"/>
<listcell label="4,274"/>
<listcell label="16.27%"/>
</listitem>
<listitem draggable="true" droppable="true" onDrop="move(event.dragged)">
<listcell label="France"/>
<listcell label="1,892"/>
<listcell label="7.20%"/> </listitem>
<listitem draggable="true" droppable="true" onDrop="move(event.dragged)">
<listcell label="Germany"/>
<listcell label="1,846"/>
<listcell label="7.03%"/>
</listitem>
<listitem draggable="true" droppable="true" onDrop="move(event.dragged)">
<listcell label="(other)"/>
<listcell label="13,162"/>
<listcell label="50.01%"/>
</listitem>
<listfoot>
<listfooter label="Total 132"/>
<listfooter label="26,267"/>
<listfooter label="100.00%"/>
</listfoot>
</listbox>
<zscript>
void move(Component dragged) {
self.parent.insertBefore(dragged, self);
}
</zscript>
</window>
当用户拖放一个列表项或tree项时,这些项目的选择状态不会改变。仅当移动拖曳项时是可视的,但是, 通过查询所有选中项的集合,你可以处理所有的选中项,如下所示。
public void onDrop(DropEvent evt) {
Set selected = ((Listitem)evt.getDragged()).getListbox().getSelectedItems();
//then, you can handle the whole set at once
}
注意,被拖曳项允许并未被选中。因此对于此事例,你或许更喜欢将选中项改变为拖曳项,如下所示。
Listitem li = (Listitem)evt.getDragged();
if (li.isSelected()) {
Set selected = ((Listitem)evt.getDragged()).getListbox().getSelectedItems();
//then, you can handle the whole set at once
} else {
li.setSelected(true);
//handle li only
}
可放下组件不接受所有的可拖曳组件是和平常的。例如,一个e-mail文件夹只接受e-mail且拒绝联系(contacts)或其它。当调用onDrop时,你可以默默地忽略不可接受的组件,或是发出警告消息。
为了获得更好的视觉效果,你可以使用一个标识来确定每种类型的可拖曳组件,然后将标识赋予draggable属性。
<listitem draggable="email"/> ... <listitem draggable="contact"/>
然后,你可以为droppable属性指定一个标识列表来限制可被放下的组件。例如,下面的图像仅接受email和contact。
<image src="/img/send.png" droppable="email, contact" onDrop="send(event.dragged)"/>
若想接受任何类型的组件,你可以将droppable属性的值设为"true"。例如,下面的图像可以接受任意类型的可拖曳组件。
<image src="/img/trash.png" droppable="true" onDrop="remove(event.dragged)"/>
另外,如果draggable属性的值为 "true",则意味着此组件属于匿名类型。此外,只有droppable属性值为"true" 的组件接受此组件。