1. Введение
В первом уроке мы создали базовое ГИС-приложение OpenMap, которое отображает карту с одним слоем фигур , загруженным из файловой системы, внутри JFrame
. Этот учебник был основан на com.bbn.openmap.app.example.SimpleMap
. В этом руководстве мы использовали следующие классы OpenMap: MapBean, PropertyHandler, ShapeLayer, com.bbn.openmap.util.SwingWorker
.
Мы добавили MapBean
в MapBean
. Тем не менее, OpenMap предоставляет собственный OpenMapFrame
, OpenMapFrame
, который может содержать MapPanel
. MapPanel
— это интерфейс (см. Рисунок 1), описывающий компонент, который содержит MapBean, MapHandler
, виджеты меню и все другие компоненты, связанные для создания виджета карты OpenMap . MapPanel
— это автономный компонент OpenMap Swing. Ожидается, что MapPanel
будет расширяться от java.awt.Container
, в противном случае он может не быть автоматически добавлен в OpenMapFrame
если он найден в MapHandler
(мы поговорим о MapHandler
позже в этой статье).
com.bbn.openmap.BufferedMapBean
расширяет MapBean
, заставляя его слои рисовать свои элементы карты в буферизованном изображении. Этот буфер рисования затем визуализируется всякий раз, когда вызывается поток Java AWT для рисования слоев. Это значительно повышает производительность, поскольку позволяет избежать (потенциально дорогого) процесса покраски Layer
. Если слой требует рисования, тогда буфер рисования восстанавливается слоями и рисуется в окне карты.
com.bbn.openmap.BufferedLayerMapBean
расширяет BufferedMapBean
специальным внутренним буфером изображений, который содержит все слои, которые были обозначены как фоновые. Этот буфер особенно полезен, когда некоторые слои анимируют движущиеся объекты карты и карту часто перекрашивают. Использование отдельного буферизованного изображения для фоновых слоев значительно сокращает время и объем работы, необходимые для рендеринга карты, увеличивая скорость обновления карты. По умолчанию приложение OpenMap использует BufferedLayerMapBean
вместо MapBean
из-за этой повышенной производительности.
2. OpenMapFrame и MapPanel
Давайте посмотрим, как мы можем изменить наш MapFram
e из предыдущего урока, чтобы воспользоваться вышеупомянутыми классами OpenMap :
- Измените
MapFrame
так, чтобы онOpenMapFrame
вместоjavax.swing.JFrame
. - Исправить импорт (Ctrl + I). При желании вы можете запустить приложение, чтобы убедиться, что оно работает как прежде.
- Переключитесь в представление «Дизайн», нажав кнопку «Дизайн».
- Выберите и удалите экземпляр
MapBean
(из окна навигации ). - Перетащите элемент
BasicMapPanel
наOpenMapFrame
из группы палитр OpenMap . - Переименуйте его в
mapPanel
. - Измените направление макета на Центр из окна Свойства .
- Вернуться к исходному виду, изменить строку
mapBean.add(shapeLayer);
tomapPanel.getMapBean().add(shapeLayer);
,
Результат показан в листинге 1 (при условии, что вы выбрали последнюю реализацию из учебника 1 ).
В качестве упражнения замените BasicMapPanel
на OverlayMapPanel
в шаге 5 выше. Различные MapPanel
(см. Рисунок 1) содержат BufferedLayerMapBean
поэтому вам не нужно ничего делать для повышения производительности.
Листинг 1. MapFrame Basic OpenMap-приложение
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
public class MapFrame extends OpenMapFrame { /** Creates new form MapFrame */ public MapFrame() { super ( "Simple Map" ); initComponents(); initMap(); } @SuppressWarnings ( "unchecked" ) private void initComponents() { mapPanel = new com.bbn.openmap.gui.BasicMapPanel(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); getContentPane().add(mapPanel, java.awt.BorderLayout.PAGE_END); pack(); } /** @param args the command line arguments */ public static void main(String args[]) { /* Create and display the form */ java.awt.EventQueue.invokeLater( () -> new MapFrame().setVisible( true ) ); } // Variables declaration - do not modify private com.bbn.openmap.gui.BasicMapPanel mapPanel; // End of variables declaration private void initMap() { CompletableFuture.supplyAsync(() -> getShapeLayer()) .thenAcceptAsync( shapeLayer -> { // Add the political layer to the map mapPanel.getMapBean().add(shapeLayer); MapFrame. this .revalidate(); }); } // ... } |
3. MapHandler
MapHandler
— это java.beans.beancontext.BeanContext
который можно рассматривать как большую MapHandler
, в которую можно добавлять или удалять объекты. Преимущество наличия объекта BeanContext
в качестве центра архитектуры состоит в том, что он отправляет события слушателям, когда изменяется его членство в объекте. Любой java.beans.beancontext.BeanContextMembershipListener
добавленный в BeanContext
, получит эти события и может использовать события для установки или обслуживания соединений с добавляемыми или удаляемыми объектами.
MapHandler
может рассматриваться как карта, в комплекте с MapBean
, MapBean
и другими компонентами управления, содержащимися в ней. Он может использоваться теми компонентами, которым необходимо получить указатель на другие объекты и сервисы. Его можно использовать для добавления или удаления компонентов в приложении во время выполнения, а все другие объекты, добавленные в MapHandler
получают уведомление о добавлении / удалении.
Давайте посмотрим, как мы можем воспользоваться MapHandler
. Модифицированный initMap()
показан в листинге 2 . Как уже упоминалось, MapHandler
можно рассматривать как большую MapHandler
в которую можно добавлять или удалять объекты. Мы получаем MapHandler
от MapPanel
. Чтобы иметь возможность добавлять слои к нему, нам нужно добавить LayerHandler
в MapHandler
. Мы добавляем к нему shapeLayer
и GraticuleLayer
. Порядок важен, то есть слой, добавленный последним, является тем, который появляется сверху. Наконец, нам нужно добавить OpenMapFrame
в MapHandler
. MapHandler
— это вещество, которое склеивает все это. Проверьте com.bbn.openmap.app.example.SimpleMap2
, тоже.
Причина, по MapHandler
существует MapHandler
, в отличие от простого использования BeanContext
, заключается в том, что это расширенный BeanContext
который отслеживает SoloMapComponent
s ( com.bbn.openmap.SoloMapComponents
). SoloMapComponent
— это интерфейс, который можно использовать для объекта, чтобы указать, что в BeanContext
одновременно имеется только один экземпляр этого типа компонента. Например, MapBean
является SoloMapComponent
, и в SoloMapComponent
может быть только один MapBean
(Highlander!). MapHandler
имеет com.bbn.openmap.SoloMapComponentPolicy
который говорит ему, что делать, если он попадает в ситуацию, когда добавляются дублирующиеся экземпляры SoloMapComponent
. В зависимости от политики MapHandler
отклонит второй экземпляр SoloMapComponent
( com.bbn.openmap.SoloMapComponentRejectPolicy
) или заменит предыдущий компонент ( com.bbn.openmap.SoloMapComponentReplacePolicy
).
Листинг 2: initMap () с использованием MapHandler
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
private void initMap() { try { // Get the default MapHandler the BasicMapPanel created. MapHandler mapHandler = mapPanel.getMapHandler(); // Set the map's center mapPanel.getMapBean().setCenter( new LatLonPoint.Double( 38.0 , 24.5 )); // Set the map's scale 1:120 million mapPanel.getMapBean().setScale(120000000f); /* * Create and add a LayerHandler to the MapHandler. The LayerHandler * manages Layers, whether they are part of the map or not. * layer.setVisible(true) will add it to the map. The LayerHandler * has methods to do this, too. The LayerHandler will find the * MapBean in the MapHandler. */ mapHandler.add( new LayerHandler()); CompletableFuture.supplyAsync(() -> getShapeLayer()) .thenAcceptAsync( shapeLayer -> { // Add the political layer to the map mapHandler.add(shapeLayer); mapHandler.add( new GraticuleLayer()); MapFrame. this .revalidate(); }); // Add the map to the frame mapHandler.add( this ); } catch (MultipleSoloMapComponentException msmce) { // The MapHandler is only allowed to have one of certain // items. These items implement the SoloMapComponent // interface. The MapHandler can have a policy that // determines what to do when duplicate instances of the // same type of object are added - replace or ignore. // In this example, this will never happen, since we are // controlling that one MapBean, LayerHandler, // MouseDelegator, etc is being added to the MapHandler. } } |
Однако многие вещи отсутствуют в этом базовом приложении. Например, никакие действия на карте, такие как увеличение / уменьшение масштаба, панорамирование и т. Д., Не могут быть выполнены. Но они могут быть легко добавлены с помощью MapHandler
. Просто добавьте соответствующие обработчики в MapHandler
внутри блока try-catch функции initMap()
как показано в листинге 3. Теперь вы можете увеличивать или уменьшать масштаб с помощью среднего колесика мыши и перемещать карту левой кнопкой мыши.
Листинг 3: initMap () с добавлением событий мыши
01
02
03
04
05
06
07
08
09
10
|
private void initMap() { //... // Add MouseDelegator, which handles mouse modes (managing mouse // events) mapHandler.add( new MouseDelegator()); // Add OMMouseMode, which handles how the map reacts to mouse // movements mapHandler.add( new OMMouseMode()); //... } |
До сих пор мы видели, как использовать: MapBean, MapHandler, LayerHandler, PropertyHandler, ShapeLayer, GraticuleLayer, OpenMapFrame
.
4. openmap.properties
Тем не менее, OpenMap является еще более гибким, чем это. С помощью технологии BeanContext
мы можем определить компоненты, которые составляют наше приложение, в файле свойств openmap.properties
. Мы уже создали openmap.properties
в нашем приложении, которое содержит свойства для слоев формы ESRI. Файл свойств может содержать свойства, определенные для определенного компонента. Определение области действия выполняется с использованием префикса свойства, поэтому свойства могут быть определены как:
prefix.property=value
Давайте начнем с префикса наших существующих свойств и посмотрим, какие изменения требуются в нашем коде.
1
2
3
4
5
|
shapePolitical.prettyName=Political Solid shapePolitical.lineColor=000000 shapePolitical.fillColor=BDDE83 shapePolitical.shapeFile=resources /map/shape/dcwpo-browse .shp shapePolitical.spatialIndex=resources /map/shape/dcwpo-browse .ssx |
PropertyHandler
поддерживает префиксы, как показано жирным шрифтом в листинге 5. В следующем уроке мы увидим, насколько полезна область видимости свойств. Поскольку следующая часть будет довольно обширной, лучше разбить ее здесь.
Листинг 5: PropertyHandler с поддержкой префиксов
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
private ShapeLayer getShapeLayer() { PropertyHandler propertyHandler = null ; try { propertyHandler = new PropertyHandler.Builder().setPropertiesFile( "./openmap.properties" ).setPropertyPrefix( "shapePolitical" ).build(); } catch (IOException ex) { Logger.getLogger(MapFrame. class .getName()).log(Level.SEVERE, null , ex); } //ShapeLayer: ShapeLayer shapeLayer = new ShapeLayer(); if (propertyHandler != null ) { shapeLayer.setProperties(propertyHandler.getPropertyPrefix(), propertyHandler.getProperties(propertyHandler.getPropertyPrefix())); } return shapeLayer; } |
5. Заключение
В этом уроке мы узнали, как использовать: MapBean, MapHandler, LayerHandler, PropertyHandler, ShapeLayer, GraticuleLayer, OpenMapFrame
. Мы также увидели гибкость, обеспечиваемую файлом openmap.properties
. Новые приложения могут быть настроены там без перекомпиляции. В следующем уроке мы увидим, как это сделать без необходимости перекомпилировать наше приложение.