正确调整嵌入在 Tabelcell 中的 Webview 的大小 [英] Correct sizing of Webview embedded in Tabelcell
问题描述
如上所述
已经取得了一些进展,现在单元格高度的计算更加真实.请参阅下面的相关改编代码.
相关变化:
- 似乎必须在执行 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);TableView table = new TableView();table.setPrefWidth(400);table.setPrefHeight(800);final TableColumn nameCol = new TableColumn("所以");final TableColumn col2 = 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 Webviews
embeded 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屋!