JavaFX 中的 WebView 控件呈现 URL 并执行 JavaScript(包括 jQuery)。我们如何在鼠标悬停时从呈现的 WebView 控件中选择一个元素并在单击时获取其 Xpath?
我尝试添加 mousemove、mouseenter 和 mouseleave,但它同时匹配多个元素(父元素和子元素)。它应该只在一个元素周围添加边框。
主要应用程序:
// main/visualuserinput/VisualUserInput.java
package visualuserinput;
import javafx.application.Platform;
import javafx.concurrent.Worker;
import javafx.embed.swing.JFXPanel;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import visualuserinput.FileUtil;
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
public class VisualUserInput extends JFrame {
private final JFXPanel jfxPanel = new JFXPanel();
private WebEngine engine;
private String url = "https://www.bezrealitky.cz/vyhledat?offerType=spolubydleni&estateType=byt&priceFrom=5000&priceTo=8000&disposition=&ownership=&construction=&equipped=&balcony=&order=timeOrder_desc&boundary=%5B%5B%7B%22lat%22%3A50.171436864513%2C%22lng%22%3A14.506905276796942%7D%2C%7B%22lat%22%3A50.154133576294%2C%22lng%22%3A14.599004629591036%7D%2C%7B%22lat%22%3A50.14524430128%2C%22lng%22%3A14.58773054712799%7D%2C%7B%22lat%22%3A50.129307131988%2C%22lng%22%3A14.60087568578706%7D%2C%7B%22lat%22%3A50.122604734575%2C%22lng%22%3A14.659116306376973%7D%2C%7B%22lat%22%3A50.106512499343%2C%22lng%22%3A14.657434650206028%7D%2C%7B%22lat%22%3A50.090685542974%2C%22lng%22%3A14.705099547441932%7D%2C%7B%22lat%22%3A50.072175921973%2C%22lng%22%3A14.700004206235008%7D%2C%7B%22lat%22%3A50.056898491904%2C%22lng%22%3A14.640206899053055%7D%2C%7B%22lat%22%3A50.038528576841%2C%22lng%22%3A14.666852728301023%7D%2C%7B%22lat%22%3A50.030955909657%2C%22lng%22%3A14.656128752460972%7D%2C%7B%22lat%22%3A50.013435368522%2C%22lng%22%3A14.66854956530301%7D%2C%7B%22lat%22%3A49.99444182116%2C%22lng%22%3A14.640153080292066%7D%2C%7B%22lat%22%3A50.010839032542%2C%22lng%22%3A14.527474219359988%7D%2C%7B%22lat%22%3A49.970771602447%2C%22lng%22%3A14.46224174052395%7D%2C%7B%22lat%22%3A49.970669964027%2C%22lng%22%3A14.400648545303966%7D%2C%7B%22lat%22%3A49.941901176098%2C%22lng%22%3A14.395563234671044%7D%2C%7B%22lat%22%3A49.948384148423%2C%22lng%22%3A14.337635637038034%7D%2C%7B%22lat%22%3A49.958376114735%2C%22lng%22%3A14.324977842107955%7D%2C%7B%22lat%22%3A49.9676286223%2C%22lng%22%3A14.34491711110104%7D%2C%7B%22lat%22%3A49.971859099005%2C%22lng%22%3A14.326815050839059%7D%2C%7B%22lat%22%3A49.990608728081%2C%22lng%22%3A14.342731259186962%7D%2C%7B%22lat%22%3A50.002211140429%2C%22lng%22%3A14.29483886971002%7D%2C%7B%22lat%22%3A50.023596577558%2C%22lng%22%3A14.315872285282012%7D%2C%7B%22lat%22%3A50.058309376419%2C%22lng%22%3A14.248086830069042%7D%2C%7B%22lat%22%3A50.073179111%2C%22lng%22%3A14.290193274400963%7D%2C%7B%22lat%22%3A50.102973823639%2C%22lng%22%3A14.224439442359994%7D%2C%7B%22lat%22%3A50.130060800171%2C%22lng%22%3A14.302396419107936%7D%2C%7B%22lat%22%3A50.116019827009%2C%22lng%22%3A14.360785349547996%7D%2C%7B%22lat%22%3A50.148005694843%2C%22lng%22%3A14.365662825877052%7D%2C%7B%22lat%22%3A50.14142969454%2C%22lng%22%3A14.394903042943952%7D%2C%7B%22lat%22%3A50.171436864513%2C%22lng%22%3A14.506905276796942%7D%2C%7B%22lat%22%3A50.171436864513%2C%22lng%22%3A14.506905276796942%7D%5D%5D&hasDrawnBoundary=1&mapBounds=%5B%5B%7B%22lat%22%3A51.58923530498002%2C%22lng%22%3A15.399838165986353%7D%2C%7B%22lat%22%3A51.58923530498002%2C%22lng%22%3A10.593319611298853%7D%2C%7B%22lat%22%3A49.626953225810375%2C%22lng%22%3A10.593319611298853%7D%2C%7B%22lat%22%3A49.626953225810375%2C%22lng%22%3A15.399838165986353%7D%2C%7B%22lat%22%3A51.58923530498002%2C%22lng%22%3A15.399838165986353%7D%5D%5D¢er=%7B%22lat%22%3A50.618326631013446%2C%22lng%22%3A12.996578888642588%7D&zoom=8&locationInput=praha&limit=15";
public VisualUserInput() {
super();
initComponents();
getContentPane().add(jfxPanel);
setSize(500, 500);
// Kill everything on closing the frame
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
private void initComponents() {
Platform.runLater(new Runnable() {
@Override
public void run() {
WebView view = new WebView();
engine = view.getEngine();
engine.setJavaScriptEnabled(true);
engine.setOnAlert(event -> {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Custom Alert");
alert.setContentText(event.getData());
alert.showAndWait();
});
engine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
if (Worker.State.SUCCEEDED.equals(newState)) {
Document doc = engine.getDocument();
Element styleNode = doc.createElement("script");
Text styleContent = null;
try {
styleContent = doc.createTextNode(FileUtil.gulp("test.js"));
} catch (IOException e) {
e.printStackTrace();
}
styleNode.appendChild(styleContent);
doc.getDocumentElement().getElementsByTagName("head").item(0).appendChild(styleNode);
System.out.println(engine.executeScript("document.documentElement.innerHTML"));
}
});
engine.load(url);
Button btn2 = new Button();
btn2.setText("JS action");
btn2.setPrefSize(100, 100);
btn2.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
engine.executeScript("testing()");
}
});
BorderPane borderPane = new BorderPane();
borderPane.setTop(btn2);
borderPane.setCenter(view);
Scene scene = new Scene(borderPane);
jfxPanel.setScene(scene);
}
});
}
public static void main(String[] args) {
VisualUserInput main = new VisualUserInput();
main.setVisible(true);
}
}
FileUtil.java:
// main/visualuserinput/FileUtil.java
package visualuserinput;
import java.io.*;
public class FileUtil {
public static String gulp(String filename) throws IOException {
StringBuilder builder = new StringBuilder();
try (InputStream stream = FileUtil.class.getClassLoader().getResourceAsStream(filename);
InputStreamReader streamReader = new InputStreamReader(stream);
BufferedReader reader = new BufferedReader(streamReader)) {
for (String s = reader.readLine(); s != null; s = reader.readLine()) {
builder.append(s).append(System.lineSeparator());
}
}
return builder.toString();
}
}
测试.js:
// resources/test.js
// inject jQuery when it's not loaded yet
if (typeof jQuery === "undefined") {
var scriptTag = document.createElement("script");
scriptTag.setAttribute("type", "text/javascript");
scriptTag.setAttribute("src", "https://code.jquery.com/jquery-3.4.1.slim.min.js");
document.getElementsByTagName("head")[0].appendChild(scriptTag);
}
$("html *").click(function (e) {
e.preventDefault();
var value = getXPath(this);
alert(value);
return false;
});
$("html *").mousemove(
function (e) {
e.preventDefault();
$(this).mouseenter(function () {
$(this).css("border", "3px solid red");
});
$(this).mouseleave(function () {
$(this).css("border", "none");
});
return false;
}
);
function getXPath(element) {
var val = element.value;
var xpath = '';
for (; element && element.nodeType === 1; element = element.parentNode) {
//alert(element);
var id = $(element.parentNode).children(element.tagName).index(element) + 1;
id > 1 ? (id = '[' + id + ']') : (id = '');
xpath = '/' + element.tagName.toLowerCase() + id + xpath;
}
return xpath;
}
function testing() {
alert("executed");
var articles = $("article");
for (var i = 0; i < articles.length; i++) {
var article = $(articles[i]);
article.addClass("ScraperTableRow");
article.css("border", "3px solid yellow");
}
}
当前结果选择了多个元素并在它们周围添加了边框。
预期结果应选择一个元素并在其周围添加边框。 单击时,它会显示一条警报,其中包含所选元素的 XPath。
最佳答案
关于javascript - 在Java中,当我们在WebView中加载HTML时,如何使用鼠标选择一个HTML元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57171927/