Posts filed under 'Swing'

SwingLabs JXMapKit and Google Maps

As promised in my last blog entry Map Application in Swing - The Easy Way in this short blog entry i would like to explain how to change the default map providers for the JXMapKit component from the SwingX-WS project.
The sample application still has the same functionality as in my first blog entry - to simply show a map in which the host cities of the Euro2008 are marked but this time using the Google Maps Tile server as provider for the map tiles. This is how the resulting application will look like:
Main Window of the Euro2008 - Host Cities Viewer with Google Maps Provider

Some (un)necessary info before...
The Google Maps Tile server can be reached at following address: http://mt.google.com.
This server is responsible for delivering the Google Maps tiles, please take a deeper look into the Google Maps API to understand how Google Map Tiles are addressed (Google Map API Coordinates). To get a tile from the Google Maps server some additional parameter are necessary for to add to the http://mt.google.com url. First we need an x and y coordinate as well as the zoom level to address a specific tile. The parameters v and n are needed for to satisfy the Google server. For example the following url:
http://mt.google.com/mt?n=404&v=w2.75&x=8937&y=5681&zoom=3 delivers a tile from the inner city of vienna at zoom level 3.


... we finally can implement our own Map Provider
A TileFactoryInfo encapsulates all information specific to a map server. This includes everything from the url to load the map tiles from to the size and depth of the tiles. Theoretically any map server can be used by installing a customized TileFactoryInfo. That's what the API of the SwingX-WS project says about the TileFactoryInfo class and that's also exactly what we need ;-)
The only thing we need to do is to construct a TileFactoryInfo object with the correct parameters for the Google Maps Tile server.

JAVA:
  1. public class GoogleMapsTileProvider {
  2.   private static final String VERSION = "2.75";
  3.   private static final int minZoom = 1;
  4.   private static final int maxZoom = 16;
  5.   private static final int mapZoom = 17;
  6.   private static final int tileSize = 256;
  7.   private static final boolean xr2l = true;
  8.   private static final boolean yt2b = true;
  9.   private static final String baseURL =
  10.     "http://mt1.google.com/mt?n=404&v=w" + VERSION;
  11.   private static final String x = "x";
  12.   private static final String y = "y";
  13.   private static final String z = "zoom";
  14.  
  15.   private static final TileFactoryInfo
  16.     GOOGLE_MAPS_TILE_INFO = new TileFactoryInfo(
  17.       minZoom, maxZoom, mapZoom, tileSize, xr2l,
  18.       yt2b, baseURL, x, y, z);
  19.  
  20.   public static TileFactory getDefaultTileFactory()
  21.     {
  22.       return (new DefaultTileFactory(
  23.         GOOGLE_MAPS_TILE_INFO));
  24.     }
  25. }

The minimal possible zoom level is 1, the maximum possible zoom level is 16, the tile size is 256x256 pixel, the x axis goes from left to right, and the y axis from top to bottom.
The following code sets the tile factory to our own implementation.

JAVA:
  1. JXMapKit mapViewer = new JXMapKit();
  2.   mapViewer.setTileFactory(
  3.     GoogleMapsTileProvider.getDefaultTileFactory());

Voila, from now on you can use the Google Maps Tiles in your own images but please note that your are using a service from Google without having signed their Terms of Use. So this guide is more for scientific purposes than to use in real world applications.

Add comment June 30th, 2008

Map Application in Swing - The Easy Way

Ever tried to visually represent geographical information in your Swing Application? Wouldn't it be nice to have something similar to Google maps available as a Swing component. Many thanks to the guys at SwingLabs who provide such an easy way to integrate mapping into your own Swing application. I'll try to illustrate the very basic functionality of the mapping component JXMapKit from the SwingX-WS project.
First of I'll give you a hint how the final application will look like:
Main Window of the Euro2008 - Host Cities Viewer
The application shows the location of the host cities of the Euro 2008 in a map.

Now to the interesting part - the Java code. First of all we have to instantiate an object from type JXMapKit:

JAVA:
  1. JXMapKit mapViewer = new JXMapKit();
  2. mapViewer.setDefaultProvider(
  3.   DefaultProviders.OpenStreetMaps);
  4. mapViewer.setDataProviderCreditShown(true);

Add the mapViewer to a JFrame and that's all you need if you would like to show the user a map from OpenStreetMap centered at London with controls for zooming and a minimap. If you would like to change where the map is centered you simply have to instantiate a GeoPosition object with coordinates and call the setAddressLocation on the JXMapKit object. For example if you would like to center the map at the city of the Euro 2008 final

JAVA:
  1. GeoPosition vienna =
  2.   new GeoPosition(48.20875, 16.372583);
  3. mapViewer.setAddressLocation(vienna);

Adding Waypoints
Waypoints are sets of coordinates that identify a point in physical space (Quote from Wikipedia). To complete the "Euro2008 - Host Cities Viewer" Application we finally add a marker on the map at the position of the eight host cities.

JAVA:
  1. GeoPosition zuerich =
  2.   new GeoPosition(47.366667, 8.55);
  3. GeoPosition basel =
  4.   new GeoPosition(47.566667, 7.6);
  5. ...
  6.    
  7. Set<Waypoint> hostCitiesEuro08 =
  8.   new HashSet<Waypoint>();
  9. hostCitiesEuro08.add(new Waypoint(zuerich));
  10. hostCitiesEuro08.add(new Waypoint(basel));
  11. ...
  12.  
  13. WaypointPainter<JXMapViewer> painter =
  14.   new WaypointPainter<JXMapViewer>();
  15. painter.setWaypoints(hostCitiesEuro08);
  16. mapViewer.getMainMap().setOverlayPainter(painter);

The WaypointPainter is responsible for painting the markers for waypoints at the map. The default WaypointPainter draws a blue balloon at the given GeoPosition.

Changing the map provider
At the moment the SwingLabs library provides two implementations for map providers. The OpenStreetMap as we have seen in this example and NASA's BlueMarble. It is possible to write your own provider. How to do this i'll post in my next blog. So stay tuned and enjoy experimenting with the great JXMapKit component from SwingLabs.
Please feel free to download the complete source code and the needed libraries for the Euro2008 application: Source Code for the Euro2008 - Host Cities Viewer

1 comment June 16th, 2008

Debugging Swing EDT Problems

I recently joined a new project, which is all about Swing GUI programing. We had a lot of weired problems that were nondeterministic. The problem was that the Swing components were accessed from multiple threads which may lead to concurrency problems, sadly Swing doesn't enforce you neither help you to prevent this mistake.

Always remember the following rule when working with swing: Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread. This rule means that every access to a swing component should occur on the Event Dispatch Thread (EDT) as soon as the component has been realized.

I was thinking of an automatic way to detect this problem in the existing source, because i have better things to do than searching for swing threading issues in more than 1000 Java files. During my research i found an interesting approach from Scott Delap. The main idea is to hook into the swing repaint request by writing a RepaintManager that checks if the call was done from the EDT. This check can be done easily with following statement: SwingUtilities.isEventDispatchThread(). You could also call EventQueue.isDispatchThread() directly to avoid one indirection as SwingUtilities.isEventDispathThread() does nothing more as just calling the corresponding EventQueue method. A working implementation to find EDT bugs can be found at the SwingHelper page. Sadly this only works for Java 1.5 and above, so I had to do some rewriting to get it working with a Java 1.4 VM (the source can be downloaded here).
This approach to find EDT bugs worked great for us, we found about 100+ violations in just a second. Sadly fixing them took a little bit longer ;-)
Please note that this approach does not find all EDT problems as not all methods from Swing cause a repaint event. Getters from Swing components are such an example.
If you would like to have a more complete solution you may be interested in this blog entry from Alexander Potochkin.

Add comment October 29th, 2007


Calendar

August 2008
M T W T F S S
« Jun    
 123
45678910
11121314151617
18192021222324
25262728293031

Posts by Month

Posts by Category