Встраивание карт в приложение на Java

236
02 июля 2018, 21:00

Мне необходимо встроить карты в моё оконное приложение на Java, не обязательно google-карты, мне нужно лишь находить место по заданным координатам, центрировать изображение на нём и далее рисовать маршрут (просто проводить линию, не как в google maps с учётом препятствий и т.д.) до новых координат и повторять цикл. Какую библиотеку лучше использовать для этого и какие методы в ней? Мой уровень знания Java начальный, до этого не работал со сторонними библиотеками.

Answer 1

Проще всего наверное использовать какую-нибудь Javascript библиотеку в JavaFX WebView (Java 8+). Например Leaflet как бесплатный вариант (FreeBSD лицензия). В этом примере создаётся карта и под ней кнопка "Test". Когда нажимаешь на кнопку то на карте медленно рисуется рандомный путь из десяти точек.

LeafletTest.java
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
public class LeafletTest extends Application {
    private WebEngine webEngine;
    private Button testButton;
    private boolean createdPath = false;
    @Override
    public void start(Stage primaryStage) throws Exception {
        WebView webView = new WebView();
        webView.setContextMenuEnabled(false);
        webEngine = webView.getEngine();
        webEngine.setJavaScriptEnabled(true);
        webEngine.load(LeafletTest.class.getResource("map.html").toExternalForm());
        JSObject window = (JSObject) webEngine.executeScript("window");
        window.setMember("app", this);
        testButton = new Button("Test");
        testButton.setDisable(true);
        StackPane browserPane = new StackPane(webView);
        browserPane.setPrefSize(600, 400);
        VBox pageContainer = new VBox(browserPane, testButton);
        Scene scene = new Scene(pageContainer);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public void mapIsReady() {
        Platform.runLater(() -> {
            testButton.setDisable(false); // button can be clicked now that the map is ready
            testButton.setOnAction((e) -> { // what happens when the button is clicked
                testButton.setDisable(true); //don't let button be clicked twice
                new Thread(() -> { // thread to slowly draw random path
                    double randomLatitude = Math.random() * 45;
                    double randomLongitude = Math.random() * 90;
                    String polyLineName = "testPath";
                    if (createdPath) {
                        removePolyline(polyLineName); // remove old one if it exists
                    }
                    newPolyline(polyLineName);
                    createdPath = true;
                    for (int i = 0; i < 10; i++) {
                        centerMap(randomLatitude, randomLongitude, 6);
                        addPointToPolyline(polyLineName, randomLatitude, randomLongitude);
                        try {
                            Thread.sleep(2000); // wait 2 seconds between drawing points
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                        randomLatitude += Math.random();
                        randomLongitude += Math.random();
                    }
                    Platform.runLater(() -> testButton.setDisable(false)); // now button can be clicked again
                }).start();
            });
        });
    }
    private void centerMap(double lat, double lon, int zoom) {
        Platform.runLater(
                () -> webEngine.executeScript("theMap.setView(new L.LatLng(" + lat + ", " + lon + "), " + zoom + ");"));
    }
    private void newPolyline(String name) {
        Platform.runLater(
                () -> webEngine.executeScript("window." + name + " = L.polyline([], {color: 'red'}).addTo(theMap)"));
    }
    private void addPointToPolyline(String name, double lat, double lon) {
        Platform.runLater(() -> webEngine
                .executeScript("window." + name + ".addLatLng(new L.LatLng(" + lat + ", " + lon + "));"));
    }
    private void removePolyline(String name) {
        Platform.runLater(() -> webEngine.executeScript("theMap.removeLayer(window." + name + ");"));
    }
    public static void main(String[] args) {
        launch(args);
    }
}
map.html
<!DOCTYPE html>
<html>
<head>
    <title>Leaflet</title>
    <meta charset="utf-8" />
    <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/>
    <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script>
</head>
<body style="margin:0; padding:0;">
<div id="mapid" style="width:600px; height:400px"></div>
<script>
    theMap = L.map('mapid').setView([0, 0], 1);
    L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
        maxZoom: 18,
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
            '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        id: 'mapbox.streets'
    }).addTo(theMap);
    // call Java program to let it know that the page is done loading
    app.mapIsReady();
</script>
</body>
</html>
READ ALSO
Анимация для изменения цвета JComponent. / Write animation for JComponent to change colors from rectangles&#39; color to grey slowly

Анимация для изменения цвета JComponent. / Write animation for JComponent to change colors from rectangles' color to grey slowly

Я хочу сделать анимацию для изменения цвета JComponent с любого на серый в течении 5 секунд/ I want to make an animation which would change JComponent's color from any color to grey and then back, but slowly,...

159
Сравнение BigDecimal

Сравнение BigDecimal

Даны две точки и середина между нимиПочему результат сравнения неверный? Изначально я использовал тип double, оказалось, что он не очень подходит...

199
Ошибка с FirebaseListAdapter

Ошибка с FirebaseListAdapter

При компиляции кода выдает ошибку:

194
Как можно отобразить несколько точек на mapView если координаты этих точек находятся в бд firebase?

Как можно отобразить несколько точек на mapView если координаты этих точек находятся в бд firebase?

Есть база данных, куда приходят данные о местоположение пользователя

175