源文转自:How to show a “Loading…” pop-up in your GWT app
Last week, I posted a technique for displaying a splash screen before GWT loads. In this post, we’ll look at a way to show a modal pop-up after your app is up and running, but while GWT is making AJAX calls.
The basic idea is to show and center a pop-up with some text and an Ajax wait image. There are a couple ways to hook it into gwt-presenter. The WidgetDisplay interface method has startProcessing() and stopProcessing() methods that get called by the DisplayCallback class that you pass to dispatch.execute(). If you want to show the pop-up for only one presenter, then you can simply implement these methods in your view. More likely, however, a centered pop-up will be used by multiple presenters, in which case we can create an AppLoadingPresenter and AppLoadingView that will listen for an AppLoadingEvent. Any presenter or service can then fire the AppLoadingEvent to cause the “Loading…” panel to be shown. Here’s some very elegant code courtesy of my co-worker Tony Richardson. I’ll leave it up to you to create the AppLoadingEvent and fire where you need it. One more note: I’m reusing the AppLoadingEvent to trigger both showing and hiding the pop-up by means of a boolean argument in the AppLoadingEvent constructor. It might be more correct to use separate events for this, but it’s getting late…
package com.roa.client.presenter; import java.util.List; import net.customware.gwt.presenter.client.EventBus; import net.customware.gwt.presenter.client.place.Place; import net.customware.gwt.presenter.client.widget.WidgetDisplay; import net.customware.gwt.presenter.client.widget.WidgetPresenter; import com.google.inject.Inject; import com.roa.client.event.AppLoadingEvent; import com.roa.client.handler.AppLoadingEventHandler; public final class AppLoadingPresenter extends WidgetPresenter<AppLoadingPresenter.Display> { public interface Display extends WidgetDisplay { void showWidget(); } private final Display display; private final EventBus eventBus; @Inject public AppLoadingPresenter(Display display, EventBus eventBus) { super(display, eventBus); this.display = display; this.eventBus = eventBus; bind(); } @Override public Place getPlace() { // We won't really use this presenter as a Place return null; } public void hideLoading() { this.display.startProcessing(); } @Override protected void onBind() { registerHandler(this.eventBus.addHandler(AppLoadingEvent.TYPE, new AppLoadingEventHandler() { @Override public void onAppLoadingEvent(boolean isComplete) { if (isComplete) { display.stopProcessing(); } else { display.startProcessing(); } } })); } @Override public void revealDisplay() { display.showWidget(); } }
And here’s the AppLoadingView. Very simple, but cool effect.
package com.roa.client.ui.web; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HasText; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.Widget; import com.google.inject.Inject; import com.roa.client.presenter.AppLoadingPresenter.Display; public final class AppLoadingView extends PopupPanel implements Display { private final FlowPanel container = new FlowPanel(); public AppLoadingView() { final Image ajaxImage = new Image("path_to_ajax_wait_image"); final Grid grid = new Grid(1, 2); grid.setWidget(0, 0, ajaxImage); grid.setText(0, 1, "Loading..."); this.container.add(grid); add(this.container); } @Override public Widget asWidget() { return this; } @Override public void stopProcessing() { hide(); } @Override public void startProcessing() { center(); show(); } @Override public void showWidget() { startProcessing(); } }