2016-10-20 3 views
0

Вот мой браузер JFrame:Выполнить скрипт Webview JavaFX

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=AIzaSyBp0GrBi5GE3OPPgEm7WdStGH7A2tGuaHk&libraries=visualization&callback=initMap"> 
</script> 

Я реализую программу, которая имеет кнопку для загрузки данных и отображать их как маркеры в Картах Google.

Я использую конструктор Брауэр, чтобы передать 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 вводит вас в заблуждение. Проблема в том, что вы загружаете карты google api async. JavaFx загрузил html-страницу, но в данный момент объект-карта не загружается.

У вас есть два варианта. Во-первых, что java загружает карты google и маркер. Во-вторых, что javascript вызывает java, когда карта загружена.

Пример 1 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.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: map\n" 
       + "  });\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=AIzaSyBp0GrBi5GE3OPPgEm7WdStGH7A2tGuaHk&libraries=visualization&callback=javaObj.initMap\";\n" 
       + "       $(\"head\").append(s);"); 

    } 
} 

Основная HTMLPage:

<!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 и для отладки. Я не знаю карты google api, поэтому я понятия не имею, почему карта приближается к этому, но это еще один вопрос.

+0

Вы - герой! – Forrest