#javascript #java #swing #google-maps #javafx-webengine
#javascript #java #swing #google-карты #javafx-веб-инженер
Вопрос:
Вот JFrame моего браузера:
public class Browser extends JFrame {
private final JFXPanel jfxPanel = new JFXPanel();
private WebEngine engine;
private final JPanel panel = new JPanel(new BorderLayout());
private final JLabel lblStatus = new JLabel();
private final JButton btnGo = new JButton("Go");
private final JTextField txtURL = new JTextField();
private final JProgressBar progressBar = new JProgressBar();
public Browser() {
super();
initComponents();
}
private void initComponents() {
createScene();
ActionListener al = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
loadURL(txtURL.getText());
}
};
btnGo.addActionListener(al);
txtURL.addActionListener(al);
progressBar.setPreferredSize(new Dimension(150, 18));
progressBar.setStringPainted(true);
JPanel topBar = new JPanel(new BorderLayout(5, 0));
topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
topBar.add(txtURL, BorderLayout.CENTER);
topBar.add(btnGo, BorderLayout.EAST);
JPanel statusBar = new JPanel(new BorderLayout(5, 0));
statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
statusBar.add(lblStatus, BorderLayout.CENTER);
statusBar.add(progressBar, BorderLayout.EAST);
panel.add(topBar, BorderLayout.NORTH);
panel.add(jfxPanel, BorderLayout.CENTER);
panel.add(statusBar, BorderLayout.SOUTH);
getContentPane().add(panel);
setPreferredSize(new Dimension(1024, 600));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
}
private void createScene() {
Platform.runLater(new Runnable() {
@Override
public void run() {
WebView view = new WebView();
engine = view.getEngine();
engine.titleProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Browser.this.setTitle(newValue);
}
});
}
});
engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
@Override
public void handle(final WebEvent<String> event) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
lblStatus.setText(event.getData());
}
});
}
});
engine.locationProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> ov, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
txtURL.setText(newValue);
}
});
}
});
engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
progressBar.setValue(newValue.intValue());
}
});
}
});
engine.getLoadWorker()
.exceptionProperty()
.addListener(new ChangeListener<Throwable>() {
public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
if (engine.getLoadWorker().getState() == FAILED) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(
panel,
(value != null)
? engine.getLocation() "n" value.getMessage()
: engine.getLocation() "nUnexpected error.",
"Loading error...",
JOptionPane.ERROR_MESSAGE);
}
});
}
}
});
jfxPanel.setScene(new Scene(view));
}
});
}
public void loadURL(final String url) {
Platform.runLater(new Runnable() {
@Override
public void run() {
File file = new File(url);
URL url;
try {
url = file.toURI().toURL();
engine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
engine.executeScript("addPoint(0,-26.487000,151.984000)");
}
}
});
engine.load(url.toString());
} catch (MalformedURLException ex) {
Logger.getLogger(Browser.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
}
Вот мой HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Heatmaps</title>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map;
var points = [];
var markers = [];
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: new google.maps.LatLng(-27.487000, 152.984000),
});
}
function addPoint(id, latitude, longitude) {
markers[id] = new google.maps.Marker({
draggable: false,
animation: google.maps.Animation.DROP,
position: new google.maps.LatLng(latitude, longitude),
map: map
});
var bounds = new google.maps.LatLngBounds();
markers.forEach(x => {
bounds.extend(x.getPosition());
})
map.fitBounds(bounds);
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBp0GrBi5GE3OPPgEm7WdStGH7A2tGuaHkamp;libraries=visualizationamp;callback=initMap">
</script>
Я внедряю программу, в которой есть кнопка для загрузки данных и отображения их в виде маркеров на Картах Google.
Я использую конструктор Brower для передачи URL в
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Browser browser = new Browser();
browser.setVisible(true);
browser.loadURL("C:/Users/User/Desktop/test.html");
}
и использовать функцию addPoint для добавления маркеров, но затем я получил эту ошибку:
Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: ReferenceError: Can't find variable: addPoint
Есть ли какой-либо способ вызвать функцию addPoint в методе loadUrl из моего Java-кода, а затем загрузить браузер?
Ответ №1:
Короткий ответ таков: «у вас проблема со временем». JavaFX WebEngine вводит вас в заблуждение. Проблема в том, что вы загружаете API карт Google асинхронно. JavaFX загрузил htmlстраницу, но maps-объект на данный момент не загружен.
Итак, у вас есть два варианта. Во-первых, java загружает карты Google и маркер. Второй заключается в том, что javascript вызывает java, когда карта загружена.
Пример для 1 вызова java all:
engine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
//engine.executeScript("addPoint(0,-26.487000,151.984000)");
JSObject win = (JSObject) engine.executeScript("window");
win.setMember("javaObj", new Bridge(engine));
engine.executeScript("javaObj.start()"); }
}
});
engine.load(url.toString());
новый Bridge.java
импортировать javafx.scene.web.WebEngine;
public class Bridge {
private WebEngine engine;
public Bridge(WebEngine engine) {
this.engine = engine;
}
public void addPoint(String id, String latitude, String longitude) {
System.out.println("adding value");
engine.executeScript(""
"var id="" id "";"
"var latitude="" latitude "";"
"var longitude="" longitude "";"
"var markers=[];"
"markers[id] = new google.maps.Marker({n"
" draggable: false,n"
" animation: google.maps.Animation.DROP,n"
" position: new google.maps.LatLng(latitude, longitude),n"
" map: mapn"
" });n"
" var bounds = new google.maps.LatLngBounds();n"
" var index;n"
" for (index = 0; index < markers.length; index) {n"
" bounds.extend(markers[index].getPosition());n"
" } "
" map.fitBounds(bounds);");
}
public void doAddPoint() {
addPoint("0", "-26.487000", "151.984000");
}
public void call() {
engine.executeScript("addPoint(0,-26.487000,151.984000)");
}
public void log(String text) {
System.out.println("log: " text);
}
public void initMap() {
engine.executeScript(""
"var map;"
// "javaObj.log("hier0");"
"map = new google.maps.Map(document.getElementById('map'), {n"
" zoom: 13,n"
" center: new google.maps.LatLng(-27.487000, 152.984000),n"
" });n"
// "javaObj.log("hier");"
"javaObj.doAddPoint();"
);
}
public void start() {
engine.executeScript("var s = document.createElement("script");n"
" s.type = "text/javascript";n"
" s.src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyBp0GrBi5GE3OPPgEm7WdStGH7A2tGuaHkamp;libraries=visualizationamp;callback=javaObj.initMap";n"
" $("head").append(s);");
}
}
Базовая Htmlстраница:
<!DOCTYPE html>
<html>
<head id="test">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<title>Heatmaps</title>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<p><b>test</b></p>
<div id="map"></div>
</body>
</html>
Пример для 2:
изменения в Browser.java
engine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
//engine.executeScript("addPoint(0,-26.487000,151.984000)");
JSObject win = (JSObject) engine.executeScript("window");
win.setMember("javaObj", new Bridge(engine));
}
}
});
engine.load(url.toString());
новый Bridge.java
public class Bridge {
private WebEngine engine;
public Bridge(WebEngine engine) {
this.engine = engine;
}
public void call() {
//System.out.println("do call");
engine.executeScript("addPoint(0,-26.487000,151.984000)");
}
}
изменения в HTML-странице:
var initMap =function() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: new google.maps.LatLng(-27.487000, 152.984000),
});
javaObj.call();
}
PS: jQuery предназначен только для загрузки скрипта Google Maps и для отладки. Я не знаю API карт Google, поэтому понятия не имею, почему карта так сильно увеличивается, но это другой вопрос.
Комментарии:
1. ты герой!