拖放

ZK允许用户在用户界面内拖曳特定的组件。例如,将文件拖至其它的目录,或将商品拖至购物车。

若一个组件可以被拖曳则它是可拖曳的。若用户可以将一个可拖曳的组件放入到某一组件内,则称该组件是可放下的(droppable)。

注: 在放下后,ZK并不假定关于发生什么的任何行为。这由应用程序开发人员编写onDrop事件监听器来决定。

如果应用程序什么也不做,被拖曳的组件只是简单的移回它的初始位置.

draggabledroppable属性

使用ZK,通过指派draggable属性除了"false"外的任何值,你可以使一个组件变为可拖曳的。若想禁用,则将其设为"false"。

<image draggable="true"/>

类似的,可以将droppable属性赋值为"true"来将一个组件变为可放下的。

<hbox droppable="true"/>

然后,用户可以拖曳一个可拖曳的组件,并将其放入一个可放下的组件。

onDrop 事件

一旦用户拖曳一个组件并将其放入可放下的另一个组件,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属性指定一个标识列表来限制可被放下的组件。例如,下面的图像仅接受emailcontact

<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" 的组件接受此组件。