正确调整嵌入在 Tabelcell 中的 Webview 的大小 [英] Correct sizing of Webview embedded in Tabelcell

查看:24
本文介绍了正确调整嵌入在 Tabelcell 中的 Webview 的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如上所述

解决方案

已经取得了一些进展,现在单元格高度的计算更加真实.请参阅下面的相关改编代码.

相关变化:

  • 似乎必须在执行 jevascript 之前调用 webview.setPrefHeight(-1);.
  • Javascript 已被修改.没有看到大的变化,但结果可能更一般

开放点:

  • 出于某种原因,我仍然需要将 + 15.0 添加到计算的高度.这是一个黑客.似乎必须在某处考虑一些额外的长度.
  • 调整列大小后重新计算的功能不是最佳的.使用 table.refresh() 会导致渲染显着延迟.

    public class TableViewSampleHTML extends Application {私有最终 ObservableList数据 = FXCollections.observableArrayList(new MyData(1L), new MyData(14L), new MyData(2L), new MyData(3L), new MyData(15L));public static void main(final String[] args) {发射(参数);}@覆盖公共无效开始(最后阶段阶段){最终场景场景 = 新场景(new Group(), 400, 800);TableViewtable = new TableView();table.setPrefWidth(400);table.setPrefHeight(800);final TableColumnnameCol = new TableColumn("所以");final TableColumncol2 = new TableColumn("啦啦");nameCol.setPrefWidth(200);col2.setCellValueFactory(new PropertyValueFactory<>("i"));nameCol.setCellValueFactory(new PropertyValueFactory<>("i"));nameCol.widthProperty().addListener((ob,oldV,newV) -> {table.refresh();} );//允许在列中显示文本流nameCol.setCellFactory(new Callback, TableCell>() {@覆盖public TableCell调用(TableColumn 列){return new TableCell() {@覆盖protected void updateItem(Long item, boolean empty) {super.updateItem(item, 空);if (item == null || empty) {设置文本(空);设置图形(空);setStyle("");} 别的 {WebView webview = new WebView();WebEngine 引擎 = webview.getEngine();webview.setPrefHeight(-1);//<- 绝对必须在这个位置(在调用 Javascript 之前)设置图形(网络视图);String textHTML = new String(new char[item.intValue()]).replace("", " <b> bold </b> normal, ");textHTML = "<正文>"+ textHTML + "</body>";engine.loadContent(textHTML);engine.documentProperty().addListener((obj, prev, newv) -> {String heightText = engine.executeScript(//<- 一些修改,得到的结果比原来的要少var body = document.body,"+ "html = document.documentElement;"+ "Math.max( body.scrollHeight , body.offsetHeight, "+ "html.clientHeight, html.scrollHeight, html.offsetHeight );").toString();System.out.println("高度文本:" + 高度文本);双倍高度 = Double.parseDouble(heightText.replace("px", "")) + 15.0;//<- 为什么需要这个 15.0??webview.setPrefHeight(height);this.setPrefHeight(height);});}}};}});table.setItems(data);table.getColumns().addAll(nameCol);table.getColumns().addAll(col2);((组)scene.getRoot()).getChildren().addAll(table);stage.setScene(场景);舞台表演();}公共静态类 MyData {私人龙我;公共 MyData(Long i) {this.i = i;}公共长 getI() {返回我;}}}

输出现在看起来像:

As mentioned here and here there is no easy way to determine the required height of a webview, until "RT-25005 Automatic preferred sizing of WebView" is implemented.

Are there any workarounds to this issue? I couldn't find a solution in SO or elsewhere. However since i think this is no uncommon problem, there needs to be a workaround. Any idea?

For Webviewsembeded in a stage I found the following solution (see here):

webView.getEngine().executeScript(
    "window.getComputedStyle(document.body, null).getPropertyValue('height')"
);

or

Double.parseDouble(webView.getEngine().executeScript("document.height").toString())

However this doesn't seem to work for Webviews embedded in a treecell, like here. In this case I always get too big numbers as a result.

Minimal running example (including recommendation of jewelsea):

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.util.Callback;
import org.w3c.dom.Document;

public class TableViewSampleHTML extends Application {

    private final ObservableList<MyData> data = FXCollections.observableArrayList(new MyData(1L), new MyData(3L), new MyData(2L), new MyData(4L), new MyData(1L));

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

    @Override
    public void start(final Stage stage) {
        final Scene scene = new Scene(new Group());

        TableView<MyData> table = new TableView<>();
        table.setPrefHeight(700);

        final TableColumn<MyData, Long> nameCol = new TableColumn("So So");
        nameCol.setMinWidth(200);
        nameCol.setCellValueFactory(new PropertyValueFactory<>("i"));

        // Allow to display Textflow in Column
        nameCol.setCellFactory(new Callback<TableColumn<MyData, Long>, TableCell<MyData, Long>>() {
            @Override
            public TableCell<MyData, Long> call(TableColumn<MyData, Long> column) {
                return new TableCell<MyData, Long>() {
                    @Override
                    protected void updateItem(Long item, boolean empty) {
                        super.updateItem(item, empty);

                        if (item == null || empty) {

                            setText(null);
                            setGraphic(null);
                            setStyle("");

                        } else {

                            WebView webview = new WebView();
                            webview.setPrefWidth(700.0);
                            WebEngine engine = webview.getEngine();

                            String textHTML = new String(new char[item.intValue()]).replace("", " <b> bold </b> normal, ");
                         //   textHTML = "<body>" 
                           //         + textHTML + "</body>";
                            engine.loadContent(textHTML);


                           setGraphic(webview);



                            engine.documentProperty().addListener((obj, prev, newv) -> {

                                    String heightText = engine.executeScript(
                                         "window.getComputedStyle(document.body, null).getPropertyValue('height')"
                                    ).toString();

                                    System.out.println("heighttext: " + heightText);
                                    webview.setPrefHeight(Double.parseDouble(heightText.replace("px", "")));
                                    this.setPrefHeight(Double.parseDouble(heightText.replace("px", "")));
                                    setGraphic(webview);

                            });





                        }
                    }
                };
            }
        });

        table.setItems(data);
        table.getColumns().addAll(nameCol);

        ((Group) scene.getRoot()).getChildren().addAll(table);

        stage.setScene(scene);
        stage.show();
    }

    public static class MyData {

        private Long i;

        public MyData(Long i) {
            this.i = i;
        }

        public Long getI() {
            return i;
        }
    }

}

Now the outout is

heighttext: 581px
heighttext: 581px

However these values seem to be too big. See screeenshot:

解决方案

Some progress has been made and cell heights are now calculated more realisticly. Kindly see the relevant the adapted code below.

Relevant changens:

  • Seems like it is mandatory to call webview.setPrefHeight(-1); before executing the jevascript.
  • Javascript has been modified. No big change seen, but maybe the result is more general

Open points:

  • For some reason i still have to add + 15.0 to the calculated height. This is a hack. Seems like some additional lenght has to be considered somewhere.
  • Functionality on recalculation after resize of column has is not optimal. Using table.refresh() causes significant delay in rendering.

    public class TableViewSampleHTML extends Application {
    
    private final ObservableList<MyData> data = FXCollections.observableArrayList(new MyData(1L), new MyData(14L), new MyData(2L), new MyData(3L), new MyData(15L));
    
    public static void main(final String[] args) {
        launch(args);
    }
    
    @Override
    public void start(final Stage stage) {
        final Scene scene = new Scene(new Group(), 400, 800);
    
        TableView<MyData> table = new TableView<>();
    
        table.setPrefWidth(400);
        table.setPrefHeight(800);
    
        final TableColumn<MyData, Long> nameCol = new TableColumn("So So");
        final TableColumn<MyData, Long> col2 = new TableColumn("la la");
        nameCol.setPrefWidth(200);
        col2.setCellValueFactory(new PropertyValueFactory<>("i"));
        nameCol.setCellValueFactory(new PropertyValueFactory<>("i"));
        nameCol.widthProperty().addListener((ob,oldV,newV) -> {table.refresh();} );
    
        // Allow to display Textflow in Column
        nameCol.setCellFactory(new Callback<TableColumn<MyData, Long>, TableCell<MyData, Long>>() {
    
            @Override
            public TableCell<MyData, Long> call(TableColumn<MyData, Long> column) {
    
                return new TableCell<MyData, Long>() {
    
                    @Override
                    protected void updateItem(Long item, boolean empty) {
                        super.updateItem(item, empty);
    
                        if (item == null || empty) {
    
                            setText(null);
                            setGraphic(null);
                            setStyle("");
    
                        } else {
                            WebView webview = new WebView();
                            WebEngine engine = webview.getEngine();
    
                            webview.setPrefHeight(-1);   // <- Absolute must at this position (before calling the Javascript)
                            setGraphic(webview);
    
                            String textHTML = new String(new char[item.intValue()]).replace("", " <b> bold </b> normal, ");
                            textHTML = "<body>" 
                                    + textHTML + "</body>";
                            engine.loadContent(textHTML);
    
    
                            engine.documentProperty().addListener((obj, prev, newv) -> {
    
                            String heightText = engine.executeScript(   // <- Some modification, which gives moreless the same result than the original
                                    "var body = document.body,"
                                    + "html = document.documentElement;"
                                    + "Math.max( body.scrollHeight , body.offsetHeight, "
                                    + "html.clientHeight, html.scrollHeight , html.offsetHeight );"
                            ).toString();
    
                            System.out.println("heighttext: " + heightText);
                            Double height = Double.parseDouble(heightText.replace("px", "")) + 15.0;  // <- Why are this 15.0 required??
                            webview.setPrefHeight(height);
                            this.setPrefHeight(height);
                            });
                        }
    
                    }
                };
            }
        });
    
        table.setItems(data);
        table.getColumns().addAll(nameCol);
        table.getColumns().addAll(col2);
    
        ((Group) scene.getRoot()).getChildren().addAll(table);
    
        stage.setScene(scene);
        stage.show();
    }
    
    public static class MyData {
    
        private Long i;
    
        public MyData(Long i) {
            this.i = i;
        }
    
        public Long getI() {
            return i;
        }
    }
    }
    

Output now looks like:

这篇关于正确调整嵌入在 Tabelcell 中的 Webview 的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆