jGISTools - Sample 3
Sample 3 - The way it's meant to be used
This sample will show how to use the library in a real world scenario, by trying to build a simple shapefile viewer.
Various aspects of the library will be demonstrated as this sample will be further develloped over time.
Architecture
This sample is built using the Model View Controller architecture and has 3 classes:
- the AppModel class represents the model of the application and stores the map model instance
- the AppWindow class represents the view of the application and holds the map pane
- the Application class contains the main(String[] args) method and represents the controller of the application
Providing feedback regarding the drawing operations - IMapDrawingListener
Often the shapefiles to be drawn have very large sizes and their rendering can take a significant amount of time.
The application displays a progress bar as long the drawing takes place. The map component provides the IMapDrawingListener so that third parties can be notified when the drawing starts and when it ends.
A demonstration of this functionality can be seen at Threaded drawing demo
The map drawing listener is defined as follows:
/** * This is listener interface for receiving events regarding * the drawing of the map. * @author Teodor Baciu * */ public interface IMapDrawingListener extends EventListener{ /** * Called when the map component started rendering the map data. */ public void mapDrawingStarted(); /** * Called after the map component finished drawing the map data. */ public void mapDrawingEnded(); }
The AppWindow class contains an inner class called MapDrawingEventHandler that implements the IMapDrawingListener. The listener is registered with the map component instance right after the component is created in the createMapPane() method of the AppWindow class.
mapComponent.addMapDrawingListener(new MapDrawingEventHandler());
Below you can see the MapDrawingEventHandler definition:
class MapDrawingEventHandler implements IMapDrawingListener { @Override public void mapDrawingEnded() { SwingUtilities.invokeLater( new Runnable() { @Override public void run() { stopIndeterminateAnimation(); } }); } @Override public void mapDrawingStarted() { SwingUtilities.invokeLater( new Runnable() { @Override public void run() { startIndeterminateAnimation("Drawing..."); } }); } }
When the drawing is started the startIndeterminateAnimation(...) method is called and when the rendering is finished the stopIndeterminateAnimation() is called. Those two methods are defined as follows:
/* * This method displays the progress bar situated * in the status bar and starts an intermitent progress * animation. * @param msg the message to be displayed in the status bar */ public void startIndeterminateAnimation(String msg) { progressBar.setVisible(true); progressBar.setIndeterminate(true); lbStatusText.setText(msg); invalidate(); } /** * Hides the progress bar and erases the * previous status message. */ public void stopIndeterminateAnimation() { progressBar.setVisible(false); progressBar.setIndeterminate(false); lbStatusText.setText(""); }
Also notice how the startIndeterminateAnimation(...) and the stopIndeterminateAnimation are called on the Event Dispatch Thread (EDT), using SwingUtilities.invokeLater(...) because those methods affect the Swing GUI. It is very important that anything that affects the GUI as result of a listener notification generated by the map component is done on the EDT.
Results
Running the sample code will get you this: