【问题标题】:Size JavaFX WebView to the minimum size needed by the document body将 JavaFX WebView 调整为文档正文所需的最小大小
【发布时间】:2014-11-08 10:38:49
【问题描述】:

我正在用 JavaFX 为我的项目编写一个自定义对话框。我需要一个变体但快速的模式来显示对话框内容。

我知道controlsFX;实际上我正在使用它,但我想在 WebView 中显示内容,这样它会更可控。

问题是关于WebView的大小我想找到文档正文的高度并将WebView的大小设置为那个。

我尝试了以下 javascript hack,但在显示对话框之前,我的大小为 0,在显示对话框之后,该值不可靠。有没有更好的解决方案或者我应该忘记它并尝试嵌入一个支持 HTML 3 的 swing 组件?

    WebView vw = new WebView();
    vw.getEngine().loadContent("<p>This is my text</p><b>Another</b><p> This is a paragraph</p><ul><li>First cause</li><li>Second cause></li></ul>");
    vw.setPrefSize(500, 50);
    vw.setOnMouseClicked(new EventHandler<MouseEvent>() {

        @Override
        public void handle(MouseEvent event) {
            // I see that executeScript doesn't work correctly even when the WebView is loaded
            Integer h = (Integer) vw.getEngine().executeScript("document.body.offsetHeight");
            System.out.println("scriptRES: " + h );
            vw.setPrefSize(400, h);
            vw.setMinSize(400, h);
            vw.setMaxSize(400, h);
        }
    });

【问题讨论】:

    标签: java javascript webview javafx


    【解决方案1】:

    JavaFX 问题跟踪器中的功能请求涵盖了 WebView 的自动调整大小支持:

    功能请求目前尚未实施或计划实施。您可以对功能请求进行投票或评论。

    据我所知,没有解决方法。早期版本的 WebView 似乎可以使用以下代码 engine.executeScript("document.width")engine.executeScript("document.height")。但这些命令在我上次尝试时不再有效。

    【讨论】:

      【解决方案2】:

      这是一个很晚的答案。

      在计算高度之前,您必须在文档上应用 ChangeListener。 请在Correct sizing of Webview embedded in Tabelcell

      找到您问题的运行示例

      但我的经验是,有时高点仍然很大。

      【讨论】:

      • 这应该是评论,而不是答案。如果这是一个重复的问题,那么vote to close 和/或在您earn 足够reputation 后发表评论。如果问题不是重复的,则针对此特定问题定制答案。
      • 我有同样的问题,在这里找不到解决方案。后来我将在这里找到的信息与其他问题的信息结合起来。我走得更远了,但出现了新的问题。所以我在问我的新问题,我在这里链接了。所以我的问题的解决方案也应该在这里回答问题。可以在我证明的链接中找到更多详细信息。我不确定如何处理这符合 SE 规则。应该关闭哪个问题(原始问题或我的扩展副本,具有有效的赏金和有效的解决方案)?
      【解决方案3】:

      在实现自动首选大小调整之前,某位博主提出了一个似乎可行的解决方案(目前)。

      可以在his website找到它的原始形式。

      它使拥有首选大小的WebView 变得如此简单

      WebViewFitContent webViewFitContent = new WebViewFitContent(html);
      yourContainer.getChildren().add(webViewFitContent);
      


      万一链接失效了,

      WebViewFitContent.java

      import javafx.application.Platform;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.collections.ListChangeListener;
      import javafx.concurrent.Worker.State;
      import javafx.geometry.HPos;
      import javafx.geometry.VPos;
      import javafx.scene.Node;
      import javafx.scene.layout.Region;
      import javafx.scene.web.WebEngine;
      import javafx.scene.web.WebView;
      import netscape.javascript.JSException;
      
      import java.util.Set;
      
      public final class WebViewFitContent extends Region {
      
          final WebView webview = new WebView();
          final WebEngine webEngine = webview.getEngine();
      
          public WebViewFitContent(String content) {
              webview.setPrefHeight(5);
      
              widthProperty().addListener(new ChangeListener<Object>() {
                  @Override
                  public void changed(ObservableValue<?> observable, Object oldValue, Object newValue) {
                      Double width = (Double)newValue;
                      webview.setPrefWidth(width);
                      adjustHeight();
                  }
              });
      
              webview.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
                  @Override
                  public void changed(ObservableValue<? extends State> arg0, State oldState, State newState)         {
                      if (newState == State.SUCCEEDED) {
                          adjustHeight();
                      }
                  }
              });
      
              webview.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
                  @Override
                  public void onChanged(ListChangeListener.Change<? extends Node> change) {
                      Set<Node> scrolls = webview.lookupAll(".scroll-bar");
                      for (Node scroll : scrolls) {
                          scroll.setVisible(false);
                      }
                  }
              });
      
              setContent(content);
              getChildren().add(webview);
          }
      
          public void setContent(final String content) {
              Platform.runLater(new Runnable(){
                  @Override
                  public void run() {
                      webEngine.loadContent(getHtml(content));
                      Platform.runLater(new Runnable(){
                          @Override
                          public void run() {
                              adjustHeight();
                          }
                      });
                  }
              });
          }
      
      
          @Override
          protected void layoutChildren() {
              double w = getWidth();
              double h = getHeight();
              layoutInArea(webview,0,0,w,h,0, HPos.CENTER, VPos.CENTER);
          }
      
          private void adjustHeight() {
              Platform.runLater(new Runnable(){
                  @Override
                  public void run() {
                      try {
                          Object result = webEngine.executeScript(
                                  "var myDiv = document.getElementById('mydiv');" +
                                          "if (myDiv != null) myDiv.offsetHeight");
                          if (result instanceof Integer) {
                              Integer i = (Integer) result;
                              double height = new Double(i);
                              height = height + 20;
                              webview.setPrefHeight(height);
                          }
                      } catch (JSException e) {
                          e.printStackTrace();
                      }
                  }
              });
          }
      
          private String getHtml(String content) {
              return "<html><body>" +
                      "<div id=\"mydiv\">" + content + "</div>" +
                      "</body></html>";
          }
      
      }
      

      注意 1:在上面我在 javascript 中添加了一个空检查,并选择打印出任何可能发生的异常而不是忽略它们。

      注意 2:有时WebView 的内容不会显示出来。如果其他人遇到这种情况,请发表评论。

      【讨论】:

      • 我已经用 JDK8u202 测试了这段代码,它似乎不起作用。
      • @Maxoudela,奇怪。我几乎可以肯定我已经在那个 JDK 上使用了它。我可以确认使用 JDK8u211 可以正常工作,因为我现在正在使用它。这是我正在使用的exact code
      • 抱歉耽搁了,感谢代码。它似乎在一个简单的情况下工作,但我试图在 TableView/SpreadsheetView 中使用它,然后它似乎不起作用。另外,我正在尝试使用相同的技术使其与宽度一起工作,但显然它根本不起作用..
      • webview 的内容丢失似乎是一个长期存在的错误...bugs.openjdk.java.net/browse/JDK-8087569。我已根据外汇支持合同重新打开它以尝试修复它...bugs.openjdk.java.net/browse/JDK-8237583。我在这里问过类似的问题:stackoverflow.com/questions/59803411。同时,在等待上游补丁的同时努力寻找解决方法。
      猜你喜欢
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 2015-06-01
      • 2023-03-11
      • 2013-02-22
      • 2014-03-13
      • 1970-01-01
      相关资源
      最近更新 更多