我在获取JavaFX TableView快照时遇到问题。我想生成一个表的图像文件而不显示舞台。除了未显示舞台时父列标签消失外,一切正常。
我有常规表格,包含样本人物(姓名,年龄,电子邮件 - >(主要,次要))数据:
TableView<Person> personTable = new TableView<>();
TableColumn<Person, String> nameColumn = new TableColumn<>( "Name" );
TableColumn<Person, Integer> ageColumn = new TableColumn<>( "Age" );
TableColumn<Person, String> emailColumn = new TableColumn<>( "Email" );
TableColumn<Person, String> primaryEmailColumn = new TableColumn<>( "Primary" );
TableColumn<Person, String> secondaryEmailColumn = new TableColumn<>( "Secondary" );
nameColumn.setCellValueFactory( cellDataFeatures -> cellDataFeatures.getValue().nameProperty() );
ageColumn.setCellValueFactory( cellDataFeatures -> cellDataFeatures.getValue().ageProperty().asObject() );
primaryEmailColumn.setCellValueFactory( cellDataFeatures -> cellDataFeatures.getValue().primaryEmailProperty() );
secondaryEmailColumn.setCellValueFactory( cellDataFeatures -> cellDataFeatures.getValue().secondaryEmailProperty() );
emailColumn.getColumns().addAll( primaryEmailColumn, secondaryEmailColumn );
personTable.getColumns().addAll( nameColumn, ageColumn, emailColumn );
personTable.setItems( generatePersonList() );
生成图像文件:
Scene scene = new Scene( personTable );
saveAsPng( personTable, "test2.png" );
如您所见,电子邮件的列标签(&#34;电子邮件&#34;)不可见。
我可以通过展示舞台,拍摄图像并隐藏舞台来解决这个问题:
Scene scene = new Scene( personTable );
stage.setScene( scene );
stage.show();
saveAsPng( personTable, "test2.png" );
stage.close();
我的目标是在不显示舞台的情况下生成第二张图片(使用&#34;电子邮件&#34;标签)。
我假设只有与它们相关联的值的列显示了图形,所以我尝试了以下内容,但无济于事:
emailColumn.setGraphic( new Label( "Test" ) );
emailColumn.setVisible( true );
emailColumn.getGraphic().setVisible( true );
saveAsPNG:
private void saveAsPng(Parent container, String path)
{
File file = new File(path);
WritableImage img = container.snapshot( null, null );
RenderedImage renderedImage = SwingFXUtils.fromFXImage(img, null);
try {
ImageIO.write(renderedImage,"png", file);
}
catch (Exception e) {
e.printStackTrace();
}
}
谢谢!
答案 0 :(得分:1)
每当您对未添加到Scene
的{{1}}进行操作时,您都缺少作为脉冲的一部分发生的JavaFX布局计算(应用CSS和布局传递)显示常规场景。
在您的情况下,由于未显示场景,您需要在执行快照之前通过手动触发CSS应用程序和布局传递来强制执行布局。
根据JavaFX JavaDoc,您可以通过调用Stage
和node.applyCss()
轻松完成此操作:
public final void applyCss()
如果需要,请将样式应用于此节点及其子节点(如果有)。此方法通常不需要直接调用,但可以与Parent.layout()一起使用,以在下一个脉冲之前调整节点大小,或者如果场景不在舞台中。
如果Node的Scene不为null,则无论此Node的CSS状态是否干净,都会将CSS应用于此Node。 CSS样式从此Node的最顶级父级应用,其CSS状态不是clean,这可能会影响其他节点的样式。如果Node不在场景中,则此方法为无操作。场景不必处于舞台中。
此方法不会调用Parent.layout()方法。通常,调用者将使用以下操作序列。
node.layout
在您的情况下,这将有效:
parentNode.applyCss();
parentNode.layout();
请注意,如果没有为场景或表设置任何大小,布局将使用其pref大小,因此在为每个列提供pref宽度之前应该很方便(可能你已经在做了)它)。