Building Maps into Your Swing Application with the JXMapViewer
Since the early days of navigation, maps have played a vital part of commerce. A sailor without a map was completely lost. Without a map, a land owner wouldn't know what they owned. Thomas Jefferson even sent Lewis and Clark on a two-year trip across the entire North American continent to bring back accurate maps. Despite this long history of mapping, things are changing quickly. Thanks to recent innovations in devices, networks, and satellites, mapping technology is set to completely explode with new ideas and applications. Google really kicked off this mapping explosion with the release of Google Maps and their acquisition of 3D mapping company Keyhole (now called Google Earth). A few enterprising developers quickly began hacking on Google Maps, creating a new application type, the mashup. However, Google Maps mashups were just the beginning.
Many websites now provide all sorts of interesting data that can
be searched, indexed, and visualized geographically. Flickr,
Craigslist, and Wikipedia are just a few of the many providers of
geodata. Yet despite all of the many ways people generate and use
geographic data, there is one common component: the map viewer.
Though much of the attention has been focused on Ajax maps from
Yahoo and Google, Swing has its own mapping component, the open
source JXMapViewer. Originally created for a JavaOne
demo, the JXMapViewer can let you embed mapping
abilities into your own Swing-based Java application (or applet).
By the end of this article, you will know how to build and run a
simple Swing application using the JXMapViewer
combined with new features in NetBeans 6
that can greatly increase your productivity.
Building a Basic Application
The JXMapViewer is an open source (LGPL) Swing
component created by the developers at SwingLabs. At its core, the
JXMapViewer is a special JPanel that
knows how to load map tiles from an image server. All of the
details of how to convert coordinates to pixels, cache tiles, and
stitch them together on screen are nicely hidden inside
JXMapViewer's API. All you need to do is add it to
your Swing application the way you would with any other
JPanel.
In this article, we will build a simple program that shows a map and lets you zoom and pan around. We will also add a few controls to show locations on the map with custom code. You can see what the application looks like in Figure 1.

Figure 1. Basic map application
The easiest way to work with the JXMapViewer is by
using a recent build of NetBeans 6, which you can get from the
NetBeans
download page. You must use Beta 2 to get the JNLP support used
at the end of this article. Like other SwingLabs projects, the
JXMapViewer will work with any IDE or Java development
tool, but this article will use NetBeans because recently added
features in NetBeans 6 will greatly increase your productivity and
let you build complex programs very quickly.
After you have NetBeans 6 installed and running, create a new project and choose the Java Desktop Application project type (Figure 2). Accept the default Application Shell type of Basic Application (Figure 3).

Figure 2. Creating a Desktop Java Application project (click for
full-size image)

Figure 3. Using the Basic Application shell (click for full-size
image)
You will now have a basic desktop application with a default form containing a menu bar, status label, and prefab resource bundles (Figure 4).

Figure 4. Empty Java desktop application
Adding the JXMapKit
Now download the latest weekly build of swingx-ws
from the SwingLabs
download page and unzip it in a lib directory inside of
your project. You can add the .jars to your project by right-clicking on the Libraries node in the Projects
inspector and choosing Add Jar/Folder. (Figure 5).
You will need to add the swingx-ws-2007_10_14.jar (the
exact name may be different, depending on which weekly build you
downloaded). You must also add the support .jars (swingx-bean.jar, swingx.jar, and
swing-worker.jar) to the
lib/swingx-ws-[YY_MM_DD]-bin/lib/cobundle directory
of your project.

Figure 5. Empty Java desktop application
Now that the .jars are added to your project, you can add the
JXMapKit to your form (I'll explain in a second why we
are using the JXMapKit instead of the
JXMapViewer). One of the new features of NetBeans 6 is
the ability to add components directly from your library .jars
without having to add them to the palette first. Navigate through
the class hierarchy of the SwingX-WS .jar in the Projects inspector
to find the org.jdesktop.swingx.JXMapKit class
(Figure 6).

Figure 6. Find the JXMapKit class
Once you have found the class, you can drag it directly into your
form. NetBeans will create a new instance of the
JXMapKit and add it (Figure 7). Note that the
drag operation will only work if all of the .jars are inside of your
project directory. That's why you must move them all to the
[projectdir]/lib directory first.

Figure 7. Dragging the JXMapKit into the form (click for full-size image)
In this example, I'm using the JXMapKit class
instead of the JXMapViewer because the kit version
includes zoom buttons, a zoom slider, and a mini-view. The
JXMapKit is just a wrapper for the
JXMapViewer that includes the most commonly used
features. Once you have added the component, you can resize it to
fill the form.
Now press the triangle-shaped run button or select Run->Run Main Project from the main menu to see your program running (Figure 8). You can drag the map around and also zoom in and out. That's it! This is your first mapping application.

Figure 8. Basic map application
Customizing the Map
Now that you have a map application, you might want to customize
it. Fortunately, the JXMapKit has many customization
options. The first things you might want to change are the visible
control components. There are properties to turn on and off the
mini-map, zoom slider, and zoom buttons. For example, if you wanted
to show the map in a smaller space, you could turn off the zoom
slider and mini-map but leave the zoom buttons visible. You can set
these properties in the Property Sheet to the left of the form
editor.
Re-Centering and Adding Waypoints
Now that you have a map, you probably want to do something with
it. The two basic operations supported by the
JXMapViewer are moving the map and adding markers. To
move the map, you can use the setAddressLocation()
method. New features in NetBeans 6 make it very easy to tie a
button to the map.
Let's make a button that will center the map on Chicago. Just
add a button to the form from the palette, and then right-click the button and choose Set Action... to open the Action
editor for that button. In the Action to edit combo box,
choose Create New Action. Next, type in the method name
goChicago and the text Go To Chicago.
(Figure 9). Finally, press the OK button to close the Action
editor. NetBeans will create the new empty goChicago
method and jump to it.

Figure 9. Creating a goChicago action (click for
full-size image)
Type this code into the method body:
jXMapKit1.setAddressLocation(new GeoPosition(41.881944,-87.627778));
The GeoPosition class represents a coordinate on
the globe expressed as a latitude and longitude. All
JXMapViewer APIs express coordinates using the
GeoPosition class. You can find the coordinates of
many cities and landmarks at Wikipedia. Each entry
has coordinates in the sidebar summary on the right side of the
screen under the map.
Now run the application and press the Go To Chicago button. The map will re-center above Chicago using the coordinates I grabbed from Wikipedia (Figure 10).

Figure 10. Centering on Chicago
The JXMapKit tracks two different positions.
Whenever you call the setAddressPosition() method, the
map will move and set a marker on the selected point. You can also
read the current center position of the map using the
getCenterPosition() method. The center position will
change whenever the user moves around the map. The address
position only changes when you call
setAddressPosition().
Adding Waypoints
To make your map really useful, you need to draw points on it
that represent locations. In the mapping world, coordinates that
represent physical locations are called waypoints. Waypoints
are represented with the WayPoint class. The
JXMapViewer has a special painter that can properly
draw points on the map. Painters are classes that implement the
Painter interface and can be set on a SwingX component
to customize that component's drawing. JXMapViewer
can accept painters using the setOverlayPainter()
method. Below is an action method that will add the points for New
York City and Chicago using the standard
WaypointPainter.
@org.jdesktop.application.Action
public void addWaypoint() {
//create a Set of waypoints
Set<Waypoint> waypoints = new HashSet<Waypoint>();
waypoints.add(new Waypoint(41.881944,-87.627778));
waypoints.add(new Waypoint(40.716667,-74));
//crate a WaypointPainter to draw the points
WaypointPainter painter = new WaypointPainter();
painter.setWaypoints(waypoints);
jXMapKit1.getMainMap().setOverlayPainter(painter);
}
Note the call to jXMapKit1.getMainMap(). JXMapKit is actually a wrapper for two instances of
the JXMapViewer; one for the main map and one for the
mini map. You can get access to those instances with the
getMainMap() and getMiniMap()
methods.
Using a Custom Waypoint Renderer
By default, waypoints are drawn using a blue teardrop shape, but
you may want to customize them with your own drawing code. You can
easily do this by implementing the WaypointRenderer
interface. Below is an addition to the code above where I have
added a custom WaypointRenderer to the painter that
draws each waypoint as a red "X."
painter.setWaypoints(waypoints);
painter.setRenderer(new WaypointRenderer() {
public boolean paintWaypoint(Graphics2D g, JXMapViewer map, Waypoint wp) {
g.setColor(Color.RED);
g.drawLine(-5,-5,+5,+5);
g.drawLine(-5,+5,+5,-5);
return true;
}
});
jXMapKit1.getMainMap().setOverlayPainter(painter);
The WaypointPainter does all necessary coordinate
calculations and pre-translates the Graphics2D object
before calling your paintWaypoint() method. This means
the center of the waypoint will be at 0,0, so creating a ten-pixel "X"
is easily accomplished by drawing from -5 to +5. References to the
map and current waypoint are provided in case your code needs to
conditionally draw certain waypoints differently. The return
Boolean is not currently used so you can just return true.
Using Alternate Map Servers
By default the JXMapKit uses a copy of NASA's Blue
Marble satellite images hosted on a SwingLabs server. The Blue
Marble data only goes to 8-km resolution, however. Another option
is the OpenStreetMap.org tile server,
which serves up a vector map of the world created by volunteers
with GPS receivers. JXMapKit is preconfigured with both maps so
you can switch between them by setting the
defaultProvider property in the Property Sheet.
You can also select custom as the defaultProvider to use your
own map server, but this is a more complicated task that I will
cover in a future article. If you select the OpenStreetMaps, your
application will look like Figure 11.

Figure 11. Using the OpenStreetMaps server
Deploying Your Application
Now that you have built a cool mapping application, you probably want to share it on the Web. One of the great new features in NetBeans 6 is support for Java Web Start deployment. To use it, you must turn on Web Start by going to the Project Properties, selecting the Web Start tab, and checking the "Enable Web Start" checkbox (Figure 12). Then you should change the codebase to "User defined (e.g. HTTP deployment)," type in the base URL where you will upload your application, and then check the "Self-signed" checkbox. Now you can build the project and upload the contents of your project's dist directory to your web server.

Figure 12. Enabling Java Web Start (click for full-size
image)
Once your application is uploaded to your web server, you can
point your browser at the uploaded JNLP file. For example, I
uploaded my application to
projects.joshy.org/articles/MapApp, so the JNLP URL is
http://projects.joshy.org/articles/MapApp/launch.jnlp.
You can test my copy of the program here.
Future Work
Thanks to recent innovations in wireless networks, GPS receivers, and general web technology, mapping is becoming cheaper and more flexible. Many people believe that mapping will eventually become a part of the fabric of the internet. Nokia believes this so much it recently paid over eight billion dollars to buy one of the premier map vendors, Navteq. And the OpenStreetMap project, mentioned earlier, has attracted a group of volunteers to the huge undertaking of building a completely free and open map of the world. I highly encourage you to check them out and consider contributing.
Mapping is becoming so important that the ability to work with
maps and geocoded data will one day be a part of every software
platform. Fortunately, with the JXMapViewer you can
easily build mapping into your own Java applications today. Come
back for my next article, where I will show you how to plug in a
custom tile server, perform coordinate transformations, add
rollovers and animation, and build mashups with several popular
web services.
Resources
- Sample code for MapApp; includes NetBeans project
- SwingLabs
- NetBeans 6
- NASA Blue Marble satellite images
- OpenStreetMap.org
- Login or register to post comments
- Printer-friendly version
- 43230 reads




Comments
hi I followed the
by ankita11 - 2010-04-14 04:39
hi I followed the instructions. but getting trouble in dragging and dropping the JXMapkit into the form . all specified .jar files added in Library ,But It isn't working. help me.i don't get the map when i
by angel54 - 2010-06-17 01:14
i don't get the map when i drag and drop the JXMap kit onto the form....did you create the lib folder
by rico16135 - 2010-07-10 00:18
did you create the lib folder inside your netbeans project folder? Re-read the instruction if you have not.does application using google
by sonalikshirsagar - 2010-07-15 23:40
does application using google map in their applications can run without getting launch on web. I am having a problem i am not able to view the google map please help.Sir I was following your
by rajupriyasandy - 2010-08-18 23:17
Sir I was following your steps for embedding google maps in swing application but drag and drop of component is not working in netbeansIDE 6.8 I am waiting for your reply with warm regards raju krishnag
by hallvardb - 2010-09-29 07:58
gProject cannot be run with
by Anonymous - 2010-10-14 04:24
Project cannot be run with non-local codebase. how can ı solve this ?Hi, I tried this project but
by rahul_tomar - 2010-10-29 07:48
Hi,
I tried this project but I am getting a runtime error like this :
Exception in thread "AWT-EventQueue-0" java.lang.NoSuchMethodError: org.jdesktop.swingx.painter.AbstractPainter.<init>(Z)V
at org.jdesktop.swingx.JXMapKit$10.<init>(JXMapKit.java:581)
at org.jdesktop.swingx.JXMapKit.<init>(JXMapKit.java:581)
at mapapp.MapView.initComponents(MapView.java:117)
at mapapp.MapView.<init>(MapView.java:36)
at mapapp.MapApp.startup(MapApp.java:19)
at org.jdesktop.application.Application$1.run(Application.java:174)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
By looking to this error it seems that JVM could not able to find the method in that class, but this I could not able to understand if the jar file is there and in that jar file this class is also present then why the method could not be found ?
Please suggest me.