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 calledGoogle Earth). A few
enterprising developers quickly began hacking on Google Maps,
creating a new application type, the
"http://en.wikipedia.org/wiki/Mashup_(web_application_hybrid)">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
"http://www.netbeans.org/community/releases/60/">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
"http://www.swinglabs.org/">SwingLabs. At its core, theJXMapViewer 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 insideJXMapViewer's API. All you need to do is add it to
your Swing application the way you would with any otherJPanel.

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" />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 theNetBeans
download page. You must use Beta 2 to get the JNLP support used
at the end of this article. Like other SwingLabs projects, theJXMapViewer 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).

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, andswing-worker.jar) to thelib/swingx-ws-[YY_MM_DD]-bin/lib/cobundle directory
of your project.

Now that the .jars are added to your project, you can add theJXMapKit to your form (I'll explain in a second why we
are using the JXMapKit instead of theJXMapViewer). 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).

Once you have found the class, you can drag it directly into your
form. NetBeans will create a new instance of theJXMapKit 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.

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. TheJXMapKit is just a wrapper for theJXMapViewer 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 selectRun->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" />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 theJXMapViewer 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 namegoChicago 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.

The GeoPosition class represents a coordinate on
the globe expressed as a latitude and longitude. AllJXMapViewer APIs express coordinates using theGeoPosition class. You can find the coordinates of
many cities and landmarks at
"http://en.wikipedia.org/wiki/Chicago">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
"http://tools.wikimedia.de/~magnus/geo/geohack.php?pagename=Chicago&params=41_52_55_N_87_37_40_W_type:city">
Wikipedia (Figure 10).

"Figure 10. Centering on Chicago" />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 thegetCenterPosition() method. The center position will
change whenever the user moves around the map. The address
position only changes when you callsetAddressPosition().

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
"http://en.wikipedia.org/wiki/Waypoint">waypoints. Waypoints
are represented with the WayPoint class. TheJXMapViewer has a special painter that can properly
draw points on the map. Painters are classes that implement thePainter 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 standardWaypointPainter.

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 thegetMainMap() 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."

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
"http://earthobservatory.nasa.gov/Newsroom/BlueMarble/">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
"http://www.openstreetmap.org/">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 thedefaultProvider 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" />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 toprojects.joshy.org/articles/MapApp, so the JNLP URL ishttp://projects.joshy.org/articles/MapApp/launch.jnlp.
You can test my copy of the program
"http://projects.joshy.org/articles/MapApp/launch.html">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
"http://www.bloomberg.com/apps/news?pid=20601087&refer=home&sid=aofyAChPI4TM">
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.

Drag Drop

before dragging and dropping, put the JXMapkit.class, which is in the "library" folder of your project, into the "source packages" folder. Then, drag and drop the JXMapkit.class, but take it from its new location which is now in the same folder with your example.java(form) file.

With the latest swingx-ws.com, when I drag JXMapKit.class from the source folder (in default package), I always get an exception:
"The class itself was found, but there was a problem initializing it, e.g., due to an exception in the static initializer, or failure in loading an additional class.
java.lang.NoClassDefFoundError: org/jdesktop/swingx/JXPanel
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at org.netbeans.modules.form.project.ProjectClassLoader.findClass(ProjectClassLoader.java:172)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.netbeans.modules.form.project.FormClassLoader.findClass(FormClassLoader.java:83)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:344)
at org.netbeans.modules.form.project.ClassPathUtils.loadClass(ClassPathUtils.java:114)
at org.netbeans.modules.form.MetaComponentCreator$5.run(MetaComponentCreator.java:1438)
at org.netbeans.modules.form.FormLAF$2.run(FormLAF.java:293)
at org.openide.util.Mutex.doEventAccess(Mutex.java:1376)
at org.openide.util.Mutex.readAccess(Mutex.java:327)
at org.netbeans.modules.form.FormLAF.executeWithLookAndFeel(FormLAF.java:276)
at org.netbeans.modules.form.MetaComponentCreator.prepareClass(MetaComponentCreator.java:1434)
at org.netbeans.modules.form.HandleLayer$NewComponentDropListener.dragEnter(HandleLayer.java:3621)
at java.awt.dnd.DropTarget.dragEnter(DropTarget.java:358)
at sun.awt.dnd.SunDropTargetContextPeer.processEnterMessage(SunDropTargetContextPeer.java:338)
at sun.lwawt.macosx.CDropTargetContextPeer.processEnterMessage(CDropTargetContextPeer.java:125)
at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEnterEvent(SunDropTargetContextPeer.java:806)
at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(SunDropTargetContextPeer.java:774)
at sun.awt.dnd.SunDropTargetEvent.dispatch(SunDropTargetEvent.java:48)
at java.awt.Component.dispatchEventImpl(Component.java:4736)
at java.awt.Container.dispatchEventImpl(Container.java:2292)
at java.awt.Component.dispatchEvent(Component.java:4703)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
at java.awt.LightweightDispatcher.retargetMouseEnterExit(Container.java:4686)
at java.awt.LightweightDispatcher.trackDropTargetEnterExit(Container.java:4637)

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 krishna

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.