I'm not sure if this is even possible. It would seem like there would be a way to do this when you click a "submit" button.
private Button getButton(String id)
{
return new AjaxButton(id)
{
private static final long serialVersionUID = 1L;
{
setEnabled(true);
}
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form)
{
debug = "Beginning a process....";
target.addComponent(debugLabel);
//Perform the first process
debug = "Beginning second process....";
target.addComponent(debugLabel);
//Perform the second process
debug = "Finishing....";
target.addComponent(debugLabel);
//Perform the third process
debug = "Done.";
target.addComponent(debugLabel);
}
#Override
protected void onError(AjaxRequestTarget target, Form form)
{
//NO-OP
}
};
}
}
If it's not possible is there an alternative to multiple real-time updates? I want it so there is a status label on the bottom updating and telling you how much progress is done in that one method.
You would have to start the process that you want to have notifications about in another thread. Then you can update user session with information about the status which will be periodically checked by some ajax Behavior bound to label.
In wicket 6 you could also use WebSocketBehavior
Just use AjaxTimerBehavior, so that it updates your label every 1-2 seconds.
Code:
add(new AbstractAjaxTimerBehavior(Duration.seconds(1))
{
#Override
protected void onTimer(AjaxRequestTarget target)
{
target.add(label);
}
});
Obviously this solution uses dumb AJAX polling, so it is only advisable to use it on an intranet or other low traffic site.
Related
I have an interface method which is supposed to return a Future object.
Future<Result> doSomething()
The implementation of this method shows some ui (javafx).
One of the ui elements has a listener, that needs to be called in order to receive the actual result, I need.
How do I achieve this?
Is there a better solution?
Here an example action I need to wait for:
// this is some framework method I cannot change
#Override
public Data execute(Data data) {
Future<Data> dataFuture = handler.doSomething(data);
// this should basically wait until the user clicked a button
return dataFuture.get();
}
// handler implementation
public Future<Data> doSomething(Data data) {
// the question is how to implement this part, to be able to
// return a future object
Button button = new Button("Wait until click");
// create thread that waits for the button click ?!????
// modify incoming data object when the button was clicked
// somehow create the Future object that's bound to the button click
return future;
}
This is what I want to achieve:
my method doSomething shows a new scene(ui) with a button on it
and returns immedeately the future object
future.get() waits until the user pressed the button
limitations: it has to be done with no extra library and on >=Java7
Use a javafx.concurrent.Task. It derives from FutureTask. There are extensive examples in the linked javadoc on Task usage.
Oracle also provide a tutorial which discusses Task usage:
Concurrency in JavaFX
I think this is what you want, but I may have understood the question, if so, please edit the question a bit to clarify requirements (perhaps with an mcve). The bit that makes me a little unsure is the part in your title "waiting for ui event?", I'm not quite sure what that means in this context.
This is a solution I was searching for. It's not very nice, since the Thread.sleep doesn't convince me.
but now you propably get an idea of what I want to achieve
// make sure this is not called on the ui thread
public Future<Data> doSomething(Data data) {
WaitingFuture future = new WaitingFuture(data);
Platform.runLater(() -> {
Button button = new Button("Wait until click");
button.setOnAction(future);
// show button on ui...
});
favouriteExecutorService.submit(future);
return future;
}
static class WaitingFuture extends Task<Data> implements EventHandler<ActionEvent> {
private Data data;
WaitingFuture(Data originalData) {
this.data = originalData;
}
private Data waitingData;
#Override
public void handle(ActionEvent event) {
waitingData = data.modify();
}
#Override
protected Data call() throws Exception {
while (waitingData == null) {
Thread.sleep(100);
}
return waitingData;
}
}
My program listens to 3 types of events: ADD, DELETE, REFRESH which is triggered by a 3rd party library component on UI. My listener looks like this:
//the timestamp is the time when the event occurs
public void listenToEvent(Event event, long timestamp){
if(event.getName().equals("ADD")){
//handle ADD event
}else if(event.getName().equals("DELETE")){
//handle DELETE event
}else if(event.getName().equals("REFRESH")){
//handle REFRESH event
}
}
The code works fine for each event, except a little problem with REFRESH event:
when refresh happened on UI, the 3rd party lib component fires consecutive 3 events in a short time, that's: ADD->DELETE->REFRESH, in this case my listener thinks there are 3 events, but actually it is only a refresh action on UI.
How can I optimise my code so that when ADD->DELETE->REFRESH happens consecutively very quickly, my listener could be smart enough to know it is only a REFRESH?
(ADD and DELETE events are NOT instances of the REFRESH event)
As I already said in the comments, the piece of code I posted below is working(tested). You will probably need some tweaking of the REFRESH_TIMEOUT and probably make it thread-safe, but I've tested the basic idea:
"If ADD event comes, create a timer for it. When DELETE comes, check if there is a timertask already. If it's not-> process DELETE. If there is -> process REFRESH. If the timer expires-> process ADD"
It's a bit of a hack, but with the information you gave, I think this solution may be the easiest thing to do. You may get into a problems if the proper events are coming faster then is your REFRESH_TIMEOUT. In that case, the logic will get a bit more complicated.
long REFRESH_TIMEOUT=100;
Timer timer = null;
MyTask myTask = null;
public void listenToEvent(Event event, long timestamp){
if(event.getName().equals("ADD")){
timer = new Timer();
timer.schedule(myTask = new MyTask(event), REFRESH_TIMEOUT);
}
if(event.getName().equals("DELETE")){
if (myTask!=null && !myTask.expired){
processRefresh(event);
timer.cancel();
}else{
processDelete(event);
}
}
}
private static class MyTask extends TimerTask {
Event event;
boolean expired;
public MyTask(Event event){
this.event=event;
}
#Override
public void run() {
expired=true;
processAdd(event);
}
}
private void processAdd(Event e){
...
}
private void processDelete(Event e){
...
}
private void processRefrsh(Event e){
...
}
After some thinking, I came up with my own solution:
That's in ADD & DELETE condition, I use Thread.sleep(1000), then get the system time, after which I compare the latest system time get in REFRESH condition, if the difference is within 1sec, then it is a refresh event.
private long timeout = 1000;
private long addEventTime;
private long deleteEventTime;
private long refreshEventTime;
public void listenToEvent(Event event, long timestamp){
if(event.getName().equals("ADD")){
Thread.sleep(timeout);
addEventTime = System.currentTimeMillis();
if((refreshEventTime - addEventTime) >timout){
//handle ADD event
}
}else if(event.getName().equals("DELETE")){
Thread.sleep(timeout);
deleteEventTime = System.currentTimeMillis();
if((refreshEventTime - deleteEventTime) >timout){
//handle DELETE event
}
}else if(event.getName().equals("REFRESH")){
refreshEventTime = System.currentTimeMillis();
//handle REFRESH event
}
}
Any guru has any comment on my solution ?
If the event api is well thought imo, I'd think that an ADD event could be an instance of a REFRESH event.
An example of this would be:
//AccidentAPI provided by FooBar Corp.
public CarAccidentEvent extends AccidentEvent {
private String carMake;
public String getMake() {
return carMake;
}
}
So, your listener would be able to do something like this:
public void listenToAccidents(AccidentEvent e) {
if (e instanceOf CarAccidentEvent) {
doStuff();
} else if (e instanceOf SkyJumpingEvent) {
doOtherStuff();
} else {
blah();
}
}
But again, this is going on the assumption that the ADD and DELETE events are instances of the REFRESH event. Though, perhaps their documentation would reveal something further about the EventAPI that may help answer the problem better.
Otherwise, you could add three attributes for the listener for the System's time in Millis which if the time in Millis is a difference greater than say 1ms, then process it, otherwise, go to the REFRESH case.
How can Differentiating browser tab close and refresh functionality.
As of now window refresh and close event doesn't have different events.
My requirement is to checking weather user already logged in or not in any of tabs,So that I wont allow him to load my app in any other tabs.
In GWT (java)
private void registerWindowCloseEvent() {
Window.addCloseHandler(new CloseHandler<Window>() {
#Override
public void onClose(CloseEvent<Window> event) {
// do something on close
}
});
}
in JavaScript/Jquery:
window.onbeforeunload = function(e) {
// do something on close
};
The above events are firing for both the events refresh and close..is there any way to differentiate.
Differentiating browser tab close and refresh functionality is really a pain because we don't have two events to know which event being fired.
But there are always some requirements :)
What I'm doing is setting one cookie in on-load and making a flag true if found that cookie and removing the cookie on browser close event.
So until unless the he closed the active tab(logged in tab), that cookie still there and if he tries to open in another tab, then the already active dialog comes.
Note:Solution provided with help of Cookies.
In
Here is the onModule() for GWT / same as onload/document.ready() for java script/Jquery.
#Override
public void onModuleLoad() {
if("already_in_browser".
equalsIgnoreCase(Cookies.getCookie("already_in_browser"))){
showAlreadyTabActiveDialog();
return;
}else{
setLoggedincookie();
}
private void setLoggedincookie() {
isLoggedintab = true; //this is a global variable
registerWindowCloseEvent();
com.google.gwt.user.client.Cookies.
setCookie("already_in_browser","already_in_browser");
}
private void showAlreadyTabActiveDialog() {
alert("You are already active in another tab");
registerWindowCloseEvent();
}
/** This event is onbeforeunload in javascript
private void registerWindowCloseEvent() {
Window.addCloseHandler(new CloseHandler<Window>() {
#Override
public void onClose(CloseEvent<Window> event) {
if(isLoggedintab ){
Cookies.removeCookie("already_in_browser");
}
}
});
}
Let me know If you found any bugs or loop holes in this.So that I'l look in to them.
I would be very happy,If some one provide a solution,without using cookies.
In my Eclipse plugin, I have a TableViewer that shows some data. These data is retrieved from a remote REST service. Therefore it takes some seconds to retrieve all items. That's why I wanted to add items to the TableViewer's ContentProvider as soon as I retrieve them. I do my REST query in a separate thread:
Thread retrieveThread = new RetrieveThread();
retrieveThread.run();
In this thread I add items to my TableViewer:
MyView.instance.addItems(items);
And the same method in the class MyView:
public void addItems(List<Result> items) {
ModelProvider.INSTANCE.addItems(items);
resultLabel.setText(ModelProvider.INSTANCE.getItems().size() + " items");
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
#Override
public void run() {
viewer.refresh();
}
});
}
I expected that this procedure will add items to my TableViewer and then refresh the view. But what happens now is that my Eclipse freezes and adds all them items at the same time. How can I do this in a more responsive way?
The issue is that you are calling the run method of your thread directly. This does not spawn a new thread, it just calls the run method in-line. retrieveThread.start() would give you the behaviour you are looking for.
However, there is a better way of doing it (at least more 'eclipse friendly'), and that is to use an Eclipse Job instead of a raw Thread.
Job retrieveJob = new Job("Retrieving Data")
{
#Override
protected IStatus run(IProgressMonitor monitor) {
// do your REST call
ModelProvider.INSTANCE.addItems(items);
// if something goes wrong - don't return ok, obviously
return Status.OK_STATUS;
}
};
retrieveJob.addJobChangeListener(new JobChangeAdapter() {
#Override
public void done(IJobChangeEvent event) {
if(event.getResult().isOK())
{
resultLabel.setText(ModelProvider.INSTANCE.getItems().size() + " items");
viewer.refresh();
}
}
});
// this will run in a background thread
// and nicely integrate with the UI
retrieveJob.schedule();
We have a ViewerFilter for a TableViewer that is a little slow, so to try to give the impression of awesomeness, we wanted to have the viewer wait 500 milliseconds before refreshing the window (otherwise, it was blocking after every key stroke).
Not having any clue what I was doing, I tried creating a class that would check if System.currentTimeMillis() was greater then the time of the last key stroke + 500 from a different thread. This just caused an Invalid thread access exception to be thrown, so I'm lost.
Edit: I was able to use TableViewer.getTable().getDisplay().asyncExec() to sidestep the invalid thread problem, but I don't like my solution, and would love to hear other suggestions.
You might want to try to turn off redraw while updating the viewer.
Viewer.getControl().setRedraw(false);
// update
Viewer.getControl().setRedraw(true);
It can sometimes give a better user experience. You can also schedule a ui-job that you cancel when the user hits a new key or modifies the text. E.g.
class RefreshJob extends WorkbenchJob
{
public RefreshJob()
{
super("Refresh Job");
setSystem(true); // set to false to show progress to user
}
public IStatus runInUIThread(IProgressMonitor monitor)
{
monitor.beginTask("Refreshing", ProgressMonitor.UNKNOWN);
m_viewer.refresh();
monitor.done();
return Status.OK_STATUS;
};
}
and then reschedule the refresh in a separate job.
private RefreshJob m_refreshJob = new RefreshJob();
private Text m_filterText;
void hookModifyListener()
{
m_filterText.addModifyListener(new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
m_refreshJob.cancel();
m_refreshJob.schedule(500);
}
});
}
If the user hits the Enter key you can schedule a refresh job without the delay,
Just wrap your code in display.syncExec, something like this:
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// check refresh time
// refresh.
}
});
You may want to look in to asyncExec too, if syncExec does not meet your needs.