【问题标题】:Getting webpage opened in another tab from hyperlink of current webpage in webview of javafx browser从javafx浏览器的webview中当前网页的超链接在另一个选项卡中打开网页
【发布时间】:2017-01-31 05:41:29
【问题描述】:

我开发了一个非常简化但功能齐全的 JavaFX Web 浏览器,用于说明我想问的问题。下面是源代码。

public class OpenInNewTab extends Application {    
@Override
public void start(Stage primaryStage)
{
    TabPane tabPane = new TabPane();       

    WebView webView = new WebView();

    Tab tab = new Tab("Home Tab");
    tab.setContent(webView);

    tabPane.getTabs().add(tab);

    webView.getEngine().load("https://www.google.co.in/?gws_rd=ssl#q=javafx");

    BorderPane root = new BorderPane();
    root.setTop(tabPane);

    Scene scene = new Scene(root, 600, 339);

    primaryStage.setTitle("Basic browser");
    primaryStage.setScene(scene);
    primaryStage.show();
}    
public static void main(String[] args)
{
    launch(args);
} }

此浏览器会从此link 加载网页。我希望当我单击任何搜索结果时,单击的超链接应在与现有“主页”选项卡相邻的新选项卡中打开。

在网上广泛搜索后,我一无所获。

请帮助我提供相关代码。谢谢。

【问题讨论】:

  • After searching on the internet extensively, I reached nowhere 您刚刚为您的问题接受的完全相同的解决方案位于我昨天在对您的另一个(非常相似)问题的评论中发布的链接中!在发布新问题之前,您不能阅读我的评论吗? here
  • 谢谢你,但我已经试过你的链接了。然而,我接受的答案是直接以对我来说具有说明性的形式。虽然我希望右键单击而不是左键单击,但我不得不满足于我所得到的。

标签: javafx


【解决方案1】:

首先,您需要找到一种方法来处理显示页面上的所有传出点击事件。我已经制作了一个辅助方法来实现这一点。它为每个链接创建一个事件侦听器,单击它将打开一个新选项卡。

private void handleUrls(Document doc) {
    NodeList links = doc.getElementsByTagName("a");
    for (int i = 0; i < links.getLength(); i++) {
        EventTarget eventTarget = (EventTarget) links.item(i);
        String link = links.item(i).toString();
        eventTarget.addEventListener("click", e -> {
            WebView webView = new WebView();
            alterWebView(webView);

            Tab tab = new Tab(link);
            tab.setContent(webView);
            tab.setClosable(true);

            webView.getEngine().load(link);

            tabPane.getTabs().add(tab);

            e.preventDefault();
        }, false);
    }
}

您可能想为标签设置一个更好的名称...我使用链接作为临时解决方案,但它又长又乱。

webView.getEngine().load(link);

上面引用的alterWebView 是另一个辅助函数。它负责跟踪加载进度。一旦Worker 什么都不做,它就会给所有的url 添加监听器。

private void alterWebView(WebView webView) {
    WebEngine engine = webView.getEngine();
    Worker worker = engine.getLoadWorker();

    worker.stateProperty().addListener((oldVal, newVal, o) -> {
        if (newVal.equals(State.RUNNING)) {
            handleUrls(engine.getDocument());
        }
    });
}

所以基本上,上面代码背后的逻辑如下:

  • 我们跟踪 WebEngine 的 State 直到页面完全加载,然后我们将事件侦听器添加到每个 url。

  • 这些侦听器在被调用时将创建一个新的WebView,并对其进行相应处理,并将其添加到新的Tab 内的TabPane。

下面是基于您的代码的完整的工作示例:

public class JavaFXTest extends Application {

    private TabPane tabPane;

    @Override
    public void start(Stage primaryStage) {
        tabPane = new TabPane();
        WebView webView = new WebView();
        alterWebView(webView);

        Tab tab = new Tab("Home Tab");
        tab.setContent(webView);
        tab.setClosable(true);

        tabPane.getTabs().add(tab);

        webView.getEngine().load("https://www.google.co.in/?gws_rd=ssl#q=javafx");

        BorderPane root = new BorderPane();
        root.setTop(tabPane);

        Scene scene = new Scene(root, 600, 339);

        primaryStage.setTitle("Basic browser");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    private void alterWebView(WebView webView) {
        WebEngine engine = webView.getEngine();
        Worker worker = engine.getLoadWorker();

        worker.stateProperty().addListener((oldVal, newVal, o) -> {
            if (newVal.equals(State.RUNNING)) {
                handleUrls(engine.getDocument());
            }
        });
    }

    private void handleUrls(Document doc) {
        NodeList links = doc.getElementsByTagName("a");
        for (int i = 0; i < links.getLength(); i++) {
            EventTarget eventTarget = (EventTarget) links.item(i);
            String link = links.item(i).toString();
            eventTarget.addEventListener("click", e -> {
                WebView webView = new WebView();
                alterWebView(webView);

                Tab tab = new Tab(link);
                tab.setContent(webView);
                tab.setClosable(true);

                webView.getEngine().load(link);

                tabPane.getTabs().add(tab);

                e.preventDefault();
            }, false);
        }
    }
}

【讨论】:

  • 非常感谢!!我编译并运行了你的代码。效果很好!再次感谢您及时准确的回复。
  • 很高兴听到这个消息 :) 您可以将我的回答标记为已接受,以便其他用户看到您找到了解决方案。
  • 我会很高兴的。由于我是非常新的用户,我将不得不找出如何将您的答案标记为已接受,但我一定会这样做。您解释逻辑的方式也非常可观。再次感谢!
  • @Dth 在State.SUCCEEDED 上致电handleUrls 会更好吗?这将确保 DOM 已完全加载。
猜你喜欢
  • 2018-12-06
  • 1970-01-01
  • 2014-02-23
  • 1970-01-01
  • 2015-11-01
  • 2012-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多