-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi,
I have been using a context menu to insert Treeitems into a tree. I am having difficulty with the following:
1. I can't seem to locate a menuitem component that is defined in a context menu popup using component.getFellow(String)
2. I am unable to receive onClick events for this menuitem
I am using ZK EE 5.0.2. I can confirm the problem exists in Firefox 3.6 and IE 8
Heres the zul code file: test3.zul
<?xml version="1.0" encoding="UTF-8"?> <zk xmlns="http://www.zkoss.org/2005/zul" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd"> <tree apply="bugshow.MyComposer3"> <treecols sizable="true"> <treecol width="30%" /> <treecol width="7%" /> <treecol width="12%"/> <treecol width="12%"/> <treecol width="17%"/> <treecol width="12%"/> <treecol width="12%"/> </treecols> <treechildren> <treeitem context="editPopup"> <treerow draggable="true" droppable="true"> <treecell> <textbox value="" inplace="true"/> </treecell> <treecell><intbox value="1"/></treecell> <treecell> <decimalbox value="0"/> </treecell> <treecell> <label value="0"/></treecell> <treecell><datebox /></treecell> <treecell><label value="0"/></treecell> <treecell> <label value="5,527"/> </treecell> </treerow> </treeitem> </treechildren> </tree> <menupopup id="editPopup"> <menu label="Insert..." > <menupopup> <menuitem id="generalInsertMenuItem" label="General" /> </menupopup> </menu> </menupopup> </zk>
Here's the Composer java code: MyComposer3.java
package bugshow; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.Menuitem; /** * MyComposer3.java: Handles onClick event from context menupopup. */ public class MyComposer3 extends GenericForwardComposer { /* * The following are handlers are for the menu pop up menus */ public void doAfterCompose(Component component) throws java.lang.Exception { super.doAfterCompose(component); Menuitem menuItem = (Menuitem) component.getFellow("generalInsertMenuItem"); menuItem.setLabel("found fellow!"); } public void onClick$generalInsertMenuItem(Event event) throws Exception { Menuitem menuItem = (Menuitem) event.getTarget(); menuItem.setLabel("Received onClick Event!"); } }
When the doAfterCompose() method is automatically invoked it throws a ComponentNotFound exception. If you comment the code out in that method you will also be able to confirm that you never receive the onClick event when you exercise the menu popup
Can you tell me what I am doing wrong so I can resolve the two problems?
Thanking you in advance,
Trevor
Hi Trevor,
The reason the Tree can't find the Menuitem is because they are in different IdSpace. You can wrap the Tree and Menubar (you put menupopup in the zul, but I assume it's menubar?) with a Window and put the composer on it:
<window apply="bugshow.MyComposer3"> <tree> // ... </tree> <menubar> // ... </menubar> </window>
And since you are using GenericForwardComposer, you don't need to use getFellow() to retrieve it:
public class MyComposer3 extends GenericForwardComposer { Menuitem generalInsertMenuItem; // auto wired public void doAfterCompose(Component component) throws Exception { super.doAfterCompose(component); generalInsertMenuItem.setLabel("found fellow!"); } public void onClick$generalInsertMenuItem(Event event) throws Exception { generalInsertMenuItem.setLabel("Received onClick Event!"); } }
Regards,
Simon
Thank you Simon. Wrapping the zul code under a window tag did get around the issues 1 and 2. I think though it has raised another issue. Specifically, when the onClick$generalInsertMenuItem() method is triggered, the target ends up being the window instead of the menuitem that was clicked.
That seems strange and not inline with what I was expecting. When a widget is clicked on in the GUI, the event.getTarget() call should return the object that was clicked on. Yet this does not seem to be the case. Its appears to be inconsistent. Have I misunderstood the way the event API is meant to work? Your thoughts would be greatly appreciated.
Here's my updated MyComposer3.java code which highlights the issue:
package bugshow; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.Menuitem; public class MyComposer3 extends GenericForwardComposer { public void onClick$generalInsertMenuItem(Event event) throws Exception { Menuitem menuItem = (Menuitem) event.getTarget(); menuItem.setLabel("Received onClick Event!"); } }
When I click on the generalInsertMenuItem (which is located in the context menu popup) I get the following exception:
SEVERE: >>java.lang.ClassCastException: org.zkoss.zul.Window cannot be cast to org.zkoss.zul.Menuitem >> at bugshow.MyComposer3.onClick$generalInsertMenuItem(MyComposer3.java:30) >> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) >> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) >> at java.lang.reflect.Method.invoke(Method.java:597) >> at org.zkoss.zk.ui.event.GenericEventListener.onEvent(GenericEventListener.java:87) >> at org.zkoss.zk.ui.impl.EventProcessor.process0(EventProcessor.java:196) >> at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:140) >> at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.process0(EventProcessingThreadImpl.java:517) >> at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.sendEvent(EventProcessingThreadImpl.java:121) >>...
Hi Trevor,
It looks strange in the first glance, but this is the correct behavior. When the onClick event is triggered on generalInsertMenuItem, it is automatically forwarded to the Window (this is GenericForwardComposer's job). Thus, the event argument we get in onClick$generalInsertMenuItem is a ForwardEvent on the Window whose original event is the onClick MouseEvent on the Menuitem. To reach the original event/target you can do this:
Component comp = ((ForwardEvent) event).getOrigin().getTarget(); // this component will be the Menuitem Menuitem menuitem = (Menuitem) comp;
Regards,
Simon
Asked: 2010-06-07 08:06:17 +0800
Seen: 1,236 times
Last updated: Jun 29 '10