正确确定Tabelcell中嵌入的Webview的大小 [英] Correct sizing of Webview embedded in Tabelcell
问题描述
如上所述
已经取得了一些进展,现在可以更真实地计算细胞高度。请参阅以下相关的改编代码。
相关更改:
- 似乎必须致电
webview.setPrefHeight(-1);
执行jevascript之前。 - Javascript已被修改。没有看到大的变化,但结果可能更为一般
开放点:
- 出于某种原因,我仍然需要将
+ 15.0
添加到计算的高度。这是一个黑客。似乎在某处需要考虑一些额外的长度。 -
在调整列大小后重新计算的功能不是最佳的。使用
table.refresh()
会导致渲染显着延迟。public class TableViewSampleHTML扩展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场景=新场景(新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();});
//允许在列中显示Textflow
nameCol.setCellFactory(new Callback< TableColumn< MyData,Long>,TableCell< MyData,Long>>(){
@Override
public TableCell< MyData,Long> call(TableColumn< MyData,Long> column){
返回新的TableCell< MyData,Long>(){
@Override
protected void updateItem(Long item,boolean empty){
super.updateItem(item,empty);
if(item == null ||空){
setText(null);
setGraphic(null);
setStyle();
} else {
WebView webview = new WebView();
WebEngine engine = webview.getEngine();
webview.setPrefHeight(-1); //< - 绝对必须在此位置(在调用Javascript之前)
setGraphic(webview);
String textHTML = new String(new char [item.intValue()])。replace(\ 0,< b> bold< / b> normal,);
textHTML =< body>
+ 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(heighttext:+ heightText);
Double height = 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);
((Group)scene.getRoot())。getChildren()。addAll(table);
stage.setScene(场景);
stage.show();
}
公共静态类MyData {
private Long i;
public MyData(Long i){
this.i = i;
}
public Long getI(){
return i;
}
}
}
输出现在看起来像:
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("\0", " <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("\0", " <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屋!