使用SwingNodes时,JavaFX阶段大小调整不一致

时间:2018-03-08 05:54:49

标签: java swing javafx

问题:我有需要使用JavaFX阶段显示的Swing内容。 Swing内容需要包含在ScrollPane内,以便在调整舞台大小时保持正常的Swing大小调整。

预期行为:首次显示舞台时,需要自动调整舞台大小以适合Swing内容(即无需滚动查看)。

实际行为:舞台部分显示Swing内容(如果舞台在节点填充之前显示)或根本未显示(如果舞台是在节点填充后显示)。

如果在添加Swing节点内容之前显示阶段:

if stage is shown *before*

如果在添加Swing节点内容后显示,然后调整大小:

if stage is shown *after* and then resized

代码:这可能包含一些冗余语句,作为我各种尝试的一部分。

public static void main(final String[] args) {
    Platform.startup(() -> {});
    Platform.runLater(() -> doSwingNodeTest());
}

protected static void doSwingNodeTest() {
    final Stage stage = new Stage();
    final ScrollPane root = new ScrollPane();
    final Scene scene = new Scene(root);
    final SwingNode node = new SwingNode();
    stage.setScene(scene);
    stage.show(); // Required here for any content to 
                  //display without resizing.
    stage.sizeToScene();

    final JPanel j = new JPanel();
    j.setLayout(new BorderLayout());
    j.add(new JLabel("Some text"), BorderLayout.NORTH);
    j.add(new JButton("Some button"), BorderLayout.CENTER);
    j.add(new JButton("East button"), BorderLayout.EAST);

    node.setContent(j);
    j.revalidate();
    node.autosize();

    root.setContent(node);
    stage.setOnShown(e -> {
        j.doLayout();
        stage.sizeToScene();
        node.autosize();
        root.autosize();
    });
    // stage.show(); // Causes an 0-sized window.
}

任何人都有任何关于发生了什么以及如何解决这个问题的线索? 谢谢!

2 个答案:

答案 0 :(得分:1)

ScrollPaneSwingNode一起控制可能非常麻烦。这就是可能发生的事情:

  1. ScrollPane是根节点,因此Scene需要告诉ScrollPane它可以为ScrollPane提供多少空间。
  2. Scene告诉ScrollPane它可以使用任意数量的空间(Scene会在初始布局期间尝试调整自身大小。)
  3. ScrollPane需要告诉其子项进行布局。由于ScrollPane可以在需要时生成滚动条,它只会告诉孩子们使用尽可能多的空间。
  4. 作为SwingNode的子项在布局阶段没有要呈现的内容,它会告诉ScrollPane它需要使用X空间量,这是某种默认值
  5. ScrollPane将自身调整为该大小。
  6. ScrollPane告诉Scene它需要那么多空间。
  7. SceneStage会相应地设置尺寸。
  8. Stage变得可见,所有内容都开始呈现。
  9. SwingNode开始渲染Swing组件。
  10. Swing组件需要更大的空间并请求SwingNode
  11. SwingNode来自ScrollPane的空间请求。
  12. ScrollPane创建滚动条并继续在小空间中呈现其子项。
  13. 至于解决方案,我找不到任何体面的解决方案。一种方法是在某处设置固定大小(ScrollpaneSceneSwingNode)。另一种方法是将滚动移动到Swing。

答案 1 :(得分:0)

另一种解决方案是简单地通过getPreferredSize()向SwingNode询问其内容应该有多大,然后使用该值来设置舞台的大小。我正在调查为什么需要软糖变量。

protected static void doSwingNodeTest() {
    final Stage stage = new Stage();
    final SwingNode node = new SwingNode();
    stage.setScene(new Scene(new ScrollPane(node)));

    final JPanel j = new JPanel();
    j.setLayout(new BorderLayout());
    j.add(new JLabel("Some text"), BorderLayout.NORTH);
    j.add(new JButton("Some button"), BorderLayout.CENTER);
    j.add(new JButton("East button"), BorderLayout.EAST);
    node.setContent(j);

    int fudge = 10;
    stage.setWidth(fudge + node.getContent().getPreferredSize().getWidth());
    stage.setHeight(fudge + node.getContent().getPreferredSize().getHeight());
    stage.show(); 

}