Skip to main content
 首页 » 编程设计

javascript之在Java中,当我们在WebView中加载HTML时,如何使用鼠标选择一个HTML元素

2026年09月08日4kenshinobiy

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&center=%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。

请您参考如下方法:

您需要阻止事件在树上传播。

请参阅此示例:

https://www.w3schools.com/jquery/event_stoppropagation.asp