Java Solaris 加入Sun中国技术社区 我的社区 注册说明
 
JDK 6.0 API 中文版
 
 
 
 
 
Java API 文档中文版
使用 JXMapViewer 将地图集成到 Swing 应用程序中
 
By Joshua Marinacci, 11/26/07  

从早期航海时代开始,地图就在贸易中扮演着重要的角色。如果没有地图,海员将完全迷失方向。如果没有地图,陆地占有者将无法掌握自己所统治的疆域。托 马斯杰斐逊甚至派遣刘易斯和克拉克花费两年的时间跨越整个北美大陆,只是为了获得精确的地图。尽管绘制地图已经有了多年历史,但是世界却发生了飞速的变化。由于设备、网络和卫星技术的不断创新,在 绘图技术中采用新的思想和应用程序已是大势所趋。随着 Google Maps 的发布(现更名为 Google Earth)以及对 3D 绘图公司 Keyhole 的成功收购,Google 真正引领了绘图技术的变革。一 些活跃的开发人员很快开始研究 Google Maps,并成功创建了一种新的应用程序类型,即 聚合 。然而,Google Maps 聚合仅仅是这场变革的开始。

如今,很多网站都提供了各种有趣的数据,可以进行搜索、索引和图形化显示。Flickr、Craigslist 和 Wikipedia 只是众多地理数据提供商中的一部分。虽 然地理数据的创建和使用方法多种多样,但是它们都有一个共同的组件:地图查看器。尽管 Yahoo 和 Google 中的 Ajax 地图非常抢眼,Swing 也提供了独有的地图绘制组件,即开源的 JXMapViewer。创建 JXMapViewer 的初衷是为了进行 JavaOne 演示,它可以让您将地图绘制功能嵌入到自己的基于 Swing 的 Java 应用程序中(或者 applet)。通 过阅读本文,您将了解如何结合使用 JXMapViewerNetBeans 6 提供的可显著提高效率的新特性构建并运行一个简单的 Swing 应用程序。

构建一个基本应用程序

JXMapViewer 是开发人员在 SwingLabs 创建的一个开源 (LGPL) Swing 组件。本质上讲, JXMapViewer 是一个特殊的 JPanel,它知道如何从图像服务器加载地图 tile 数据。关于如何将坐标转换为像素、缓存 tile 数据以及在屏幕中将 tile 数据组合起来的所有细节都很好地隐藏在 JXMapViewer 的 API 中。用户只需将地图添加到 Swing 应用程序中,操作方法和其他 JPanel 相同。

在本文中,我们将构建一个简单的程序来显示地图并进行缩放和上下移动。我们还将通过定制代码添加一些控件,以显示地图中的位置。图 1 显示了这个应用程序的外观。

图 1. 基本地图应用程序
图 1. 基本地图应用程序

操作 JXMapViewer 的最简便方法是使用 NetBeans 6 提供的最新构建,可从 NetBeans 下载页面 获得。您必须使用 Beta 2 获得本文结束部分所使用的 JNLP 支持。与其他 SwingLabs 项目相同, JXMapViewer 可以与任何 IDE 或 Java 开发工具结合使用,但是本文选择使用 NetBeans,因为 NetBeans 6 最近添加的一些特性可以极大地提供效率并使您能够非常快速地构建复杂程序。

安装并运行 NetBeans 6 后,创建一个新的项目,在项目类型中选择 Java Desktop Application 项目(参见图 2)。在 Application Shell 类型中,接 受默认的 Basic Application(参见图 3)。

图 2. 创建一个 Desktop Java Application 项目
图 2. 创建一个 Desktop Java Application 项目(单击查看完整图像)

图 3. 使用 Basic Application shell
图 3. 使用 Basic Application shell(单击查看完整图像)

我们已经创建了一个基本的桌面应用程序。该应用程序提供了一个默认表单,其中包含菜单栏、状态标签和预制资源包(参见图 4)。

图 4. 空白 Java 桌面应用程序
图 4. 空白 Java 桌面应用程序

添加 JXMapKit

现在,从 SwingLabs 下载页面 下载最新版本的 swingx-ws,并将其解压缩到项目的 lib 目录。在 Projects 查看器中右键单击 Libraries 节点,并选择 Add Jar/Folder,可以将 .jar 文件添加到您的项目 (参见图 5)。我们需要添加 swingx-ws-2007_10_14.jar(根据下载的构建版本,具体名称可能会有所不同)。我们还必须将一些支持 .jar 文件( swingx-bean.jarswingx.jarswing-worker.jar)添加到项目的 lib/swingx-ws-[YY_MM_DD]-bin/lib/cobundle 目录。

图 5. 空白 Java 桌面应用程序
图 5. 空白 Java 桌面应用程序

我们已经将 .jar 文件添加到了项目中,接下来可以将 JXMapKit 添加到表单中(我将解释使用 JXMapKit 而不使用 JXMapViewer 的原因)。NetBeans 6 其中的一个新特性就是能直接在库中添加组件,而不必将它们先添加到选项板中。在 Project 查看器中浏览 SwingX-WS .jar 的类结构,找到 org.jdesktop.swingx.JXMapKit(参见图 6)

图 6. 查找 JXMapKit 类
图 6. 找到 JXMapKit

找到该类后,可将它直接拖拽到表单。NetBeans 将创建一个新的 JXMapKit 实例并添加它 (参见图 7)。注意,只有在项目目录包含所有 .jar 文件时拖拽操作才有效。这就是需要首先将它们全部移至 [projectdir]/lib 目录的原因。

图 7. 将 JXMapKit 拖拽到表单
图 7. 将 JXMapKit 拖拽到表单(单击查看完整图像)

在这个例子中,我使用了 JXMapKit 类,而没有使用 JXMapViewer,这是因为此工具版本包含一些缩放按钮、一个缩放滑块和一个迷你视图。 JXMapKit 其实是 JXMapViewer 的包装器,包含了大多数常用特性。添加了这个组件之后,您可以重新调整它的大小来填充表单。

现在,按下三角形的运行按钮或从主菜单中选择 Run->Run Main Project 来查看程序运行(参见图 8)。您可以来回拖拽地图并进行缩放操作。这就是您的第一个地图绘制应用程序。

图 8. 基本地图应用程序
图 8. 基本地图应用程序

定制地图

现在已经具备了一个地图应用程序,您可能希望对它进行定制。幸运的是, JXMapKit 提供了很多定制选项。首先需要修改的可能是可见控件组件。一些属性可以关闭和打开迷你地图、缩放滑块和缩放按钮。例如,如果希望使用更小的空间显示地图,您 可以关闭缩放滑块和迷你地图,而仅使缩放按钮可见。可以在表单编辑器左边的 Property Sheet 中设置这些属性。

重新确定中心并添加航点

现在您拥有一个地图,可能希望对它执行一些操作。 JXMapViewer 支持两种基本操作:移动地图和添加标记。要移动地图,可以使用 setAddressLocation() 方法。NetBeans 6 提供的新特性可以轻松地将按钮绑定到地图中。

让我们创建一个按钮,将芝加哥作为地图的中心。从选项板中拖动一个按钮到表单中,然后右键单击该按钮并选择 Set Action... 来打开该按钮的 Action 编辑器。在 Action to edit 复选框中,选择 Create New Action。接下来,输入方法名 goChicago 和文本 Go To Chicago(参见图 9)。最后,单击 OK 按钮关闭 Action 编辑器。NetBeans 将创建一个新的空 goChicago 方法并跳转到该方法。

图 9. 创建一个 goChicago 操作
图 9. 创建一个 goChicago 操作(单击查看完整图像)

将下面的代码添加到方法中:

jXMapKit1.setAddressLocation(new GeoPosition(41.881944,-87.627778));

GeoPosition 类使用经度和纬度表示地球坐标。所有 JXMapViewer API 都使用 GeoPosition 类表示坐标。您可以在 Wikipedia 中查看许多城市和地点的坐标。在地图下方的屏幕右侧,侧 栏摘要将显示每个条目的坐标。

现在运行应用程序并按下 Go To Chicago 按钮。地图将使用从 Wikipedia( 参见图 10)获得的坐标回到以芝加为中心的区域。

图 10. 以芝加哥为中心
图 10. 以芝加哥为中心

JXMapKit 跟踪两个不同的位置。当调用 setAddressPosition() 方法时,地图将进行移动并在所选择的点设置一个标记。您还可以使用 getCenterPosition() 方法读取地图的当前中心位置。只要用户移动地图,中心位置就会发生改变。只有在调用 setAddressPosition() 时才会改变地址位置。

添加航点

要让地图真正有用,需要在其上描绘表示位置的点。在地图绘制领域,表示物理位置的坐标称为 航点。航点使用 WayPoint 类表示。 JXMapViewer 含有一个特殊的绘图程序,可以在地图中正确地描绘点。绘图程序就是一些可实现 Painter 接口的类,可以对 SwingX 组件设置该程序以对该组件进行定制绘图。 JXMapViewer 允许绘图程序使用 setOverlayPainter() 方法。下面所示的操作方法将使用标准的 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);
}

需要注意对 jXMapKit1.getMainMap() 的调用。 JXMapKit 实际上是两个 JXMapViewer 实例的包装器;一个实例用于主地图,另一个用于迷你地图。您可以使用 getMainMap()getMiniMap() 方法访问这些实例。

使用定制航点呈现程序

默认情况下,将使用蓝色泪状物绘制航点,但是也许您希望使用自己的绘制代码对航点进行定制。通过实现 WaypointRenderer 接口可以轻松地达到这一目的。下面对上文的代码进行了补充,我向绘图程序添加了一个定制 WaypointRenderer,将每个航点绘制成一个红色的 “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);

WaypointPainter 执行所有必要的坐标计算并在调用 paintWaypoint() 方法前对 Graphics2D 对象进行预先转换。这就是说,航点的中心将为 0,0,因此,通过在 -5 到 +5 之间绘图,可以轻松地创建一个 10 像素的 “X”。我 还提供了地图参考和当前航点,以便代码根据条件绘制不同的特定航点。返回 Boolean 当前并未使用,因此返回 true 即可。

使用备用地图服务器

默认情况下,JXMapKit 使用 NASA 的 Blue Marble 卫星图像 的一个副本,由 SwingLabs 服务器托管。然而,Blue Marble 数据的分辨率只有 8 千米。另一种方法是使用 OpenStreetMap.org tile 服务器,它提供了由志愿者使用 GPS 接收器创建的世界矢量地图。 JXMapKit 对这两种地图都进行了预配置,因此,可通过在 Property Sheet 中设置 defaultProvider 属性在这两者之间切换。

您也可以选择 custom 作为 defaultProvider,从而使用自己的地图服务器。但是这项任务较为复杂,我将在未来文章中予以介绍。如果选择使用 OpenStreetMaps,则应用程序应如图 11 所示。

图 11. 使用 OpenStreetMaps 服务器
图 11. 使用 OpenStreetMaps 服务器

部署应用程序

现在,您已经构建好了一个非常不错的地图绘制应用程序,可能希望通过网络共享该程序。NetBeans 6 提供的一大新特性就是支持 Java Web Start 部署。要使用该特性,必须启用 Web Start,方法为打开 Project Properties,选择 Web Start 选项卡,然后选择 “Enable Web Start” 复选框(参见图 12)。随后应将代码库切换为 “ User defined(如 HTTP 部署)”,输入上传应用程序的目标 Base URL,然后选择 “Self-signed” 复选框。现在,您可以构建项目并将项目的 dist 目录的内容上传到您的 web 服务器。

图 12. 启动 Java Web Start
图 12. 启动 Java Web Start(单击查看完整图像)

将应用程序上传到 web 服务器后,可以将浏览器指向上传的 JNLP 文件。例如,我将我的应用程序上传到 projects.joshy.org/articles/MapApp,因此 JNLP URL 为 http://projects.joshy.org/articles/MapApp/launch.jnlp。您可以在 这里 测试我的程序副本。

结束语

无线网络、GPS 接收器和通用 web 技术的创新减少了地图绘制的成本并增加了灵活性。很多人坚信,地图绘制最终成为互联网结构的一部分。诺基亚对此深信不疑,该公司 最近以 80 亿美元收购了一家大型地图供应商 Navteq。而上文提到的 OpenStreetMap 项目吸引了众多志愿者参与构建完全免费和开源的世界地图。我强烈建议您参与到这个项目中来。

地图绘制变得日益重要,因此,处理地图和地理编码数据的功能将最终成为所有软件平台的一部分。幸运的是,现在,借助 JXMapViewer,您可以轻松地将地图绘制功能构建到自己的 Java 应用程序中。敬请关注下一篇文章,我将向您展示如何插入定制 tile 服务器、执行坐标转换、添 加翻转和动画效果,并使用一些流行的 web 服务构建聚合应用程序。

参考资料