-
FEATURED COMPONENTS
First time here? Check out the FAQ!
I'd like to implement a progress bar (progressmeter) that would display progress of the Listitems processed. For example: I have a multiple selection Listbox. A user selects a random number of listitems and clicks a button. Now the controller has to extract the value from each listitem and send it to a web service (as shown in a code below).
public void onClick$process() throws Exception {
Set<Listitem> set = box.getSelectedItems();
ListModel<Person> model = box.getModel();
Person p = null;
int cnt = 1;
int allItems = set.size();
for (Listitem it : set) {
p = model.getElementAt(it.getIndex());
/* Call a WebService */
someWS.doSomething(p);
Integer percent = cnt * 100 / allItems;
progress.setValue(percent);
cnt++;
}
}
Problem in the code above is that the progressmeter on the client side is only updated (repainted) when the controller finishes. This means that for (example) 4 selected items the progressmeter doesn't go 0 -> 25 -> 50 -> 75 -> 100 instead it just goes 0 -> 100. In previous cases when refreshing was the problem i used Events.echoEvent() function, but I think it's not of much use here.
Any ideas how to fix this??
Regards Goran
Hi Neus,
You can put the for loop inside the thread:
Thread myThread = new Thread(){ public void run(){ try { for (int i = 0; i <= 100; i += 10) { //Do something percent = i; System.out.println("El otro thread " + i); que.publish(new Event("onActualizaProgreso",null,percent)); Thread.sleep(1000); } } catch (Exception e) { e.printStackTrace(); } } }; myThread.start();
Regards,
Ben
Following this http://stackoverflow.com/questions/9274847/illgalthreadstateexception I created the thread inside the loop. It doesn't throw the exception but the progressmeter is not updated for every iteration. I realize that the event called inside the thread (where the progressmeter is updated) is called at the end of the process.
It seems that it works. But the start() is inside a for loop (the progressmeter has to be updated in every iteration) and I think it is a problem. It's giving me this exception:
GRAVE: >>java.lang.IllegalThreadStateException >> at java.lang.Thread.start(Unknown Source) >> at org.sts.generales.PantallasZul.Componentes.GestionU2.VentanaAcciones.onClick$BTNProcesar(VentanaAcciones.java:604) >> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) >> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) >> at java.lang.reflect.Method.invoke(Unknown Source) >> at org.zkoss.zk.ui.event.GenericEventListener.onEvent(GenericEventListener.java:88) >> at org.zkoss.zk.ui.AbstractComponent.onEvent(AbstractComponent.java:2734) >> at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:2705) >> at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:2646) >> at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:136) >> at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.process0(EventProcessingThreadImpl.java:534) >> at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.sendEvent(EventProcessingThreadImpl.java:126) >> at org.zkoss.zk.ui.event.Events.sendEvent(Events.java:321) >> at org.zkoss.zk.ui.event.Events.sendEvent(Events.java:331) >> at org.zkoss.zk.ui.AbstractComponent$ForwardListener.onEvent(AbstractComponent.java:3172) >> at org.zkoss.zk.ui.AbstractComponent.onEvent(AbstractComponent.java:2734) >> at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:2705) >> at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:2646) >> at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:136) >> at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.process0(EventProcessingThreadImpl.java:534) >> at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.run(EventProcessingThreadImpl.java:461)
I've never worked with threads before so I don't know how to use their methods.
Thank you
Hi,
I have the same problem. I have a progressmeter that is painted when the controller finishes (it goes from 0->100). I tried with the EventQueues but I don't success, the behaviour is always the same.
I tried something like this:
final EventQueue que = EventQueues.lookup("actualizaProgreso", EventQueues.APPLICATION, true); que.subscribe(new EventListener() { public void onEvent(Event evt) { progresoAcciones.setValue(Integer.valueOf(evt.getData().toString()));//Mostramos el pocentaje en el progressbox } }); Thread myThread = new Thread(){ public void run(){ System.out.println("El otro thread"); que.publish(new Event("onActualizaProgreso",null,percent)); } }; for (Iterator<Listitem> it = listItemsSeleccionados.iterator(); it.hasNext(); i++) { //Do something percent = i * 100/todos; myThread.run(); }
Have anyone of you solved it? Apiening you say it was easy to solve, can you post your solution please?
Thank you!
Hi gekkio thank you so much!
I haven't thought that this is could be that easy to solve. I passed a reference to the EventQueue via the constructor of my Runnable class to eliminate the lookup there. It works perfectly well now.
Thank you for your explanation!
If you take a closer look at the exception, there are two things that you should note:
- The message is "Not in an execution"
- The exception is thrown inside the lookup method
The problem is that you cannot lookup an EventQueue without being in an execution (= HTTP Request thread). It's very easy to fix: lookup the EventQueue before starting your thread.
This is the basic idea:
final EventQueue eq = EventQueues.lookup(...); Thread myThead = new Thread() { public void run() { // ... eq.publish(...); } } myThread.start();
Really no one with an idea on that?
I've experimented any further with a second .zul file (update.zul) with it's own GenericForwardComposer. In its overridden doAfterCompose method I can publish events with the same code from my previous example and it works without errors.
The update.zul page blocks while processing the working code and sending the update events to the progress bar, but the progress is displayed on my primary page like I want.
I understand that I have two independent requests now: One blocking while doing the calculation and sending updates via the EventQueue to the primary page and one which loads up and handles the events from the queue non blocking. This way I doesn't even need to create an extra thread manually. But how can I get this working with only one page? I tried to load the second zul file with Executions.createComponents but then the whole page blocks again without processing the updates.
This problem gets somehow annoying... anyone with a hint?
I have found a documentation for EventQueues here: http://books.zkoss.org/wiki/Small_Talks/2009/August/ZK_5:_Chat_with_Event_Queue
I tried to register a basic listener like this:
//Create the event queue und bind the listener EventQueues.lookup("my super queue", EventQueues.SESSION, true).subscribe( new EventListener() { public void onEvent(Event evt) { System.out.println("Event handler called"); } });
And I created a Thread that is started in a button click event listener. In the run-method the thread sends an event like this:
EventQueues.lookup("my super queue", EventQueues.SESSION, true).publish(new Event("onSomethingHapping", null, new Integer(43)));
But after starting the thread I get an exception:
Exception in thread "Thread-45" java.lang.IllegalStateException: Not in an execution at org.zkoss.zk.ui.event.impl.EventQueueProviderImpl.lookup(EventQueueProviderImpl.java:43) at org.zkoss.zk.ui.event.EventQueues.lookup(EventQueues.java:127) at ProgressThread.run(ProgressThread.java:23) at java.lang.Thread.run(Thread.java:722)
What does this mean and how can I get around this?
Thank you!
Asked: 2012-03-20 13:46:49 +0800
Seen: 593 times
Last updated: Jun 10 '13