获取JavaFX中节点的高度(生成布局传递)

时间:2014-10-02 00:10:27

标签: java javafx vbox

如何在JavaFX中获取节点的高度或者更喜欢高度,我有3 VBox并且我想将节点添加到最自由的面板,例如:

           Childrens      Total Height of the children's(Sum)
VBoxA          5                     890
VBoxB          4                     610
VBoxC          2                     720

在这种情况下,最自由的是VBoxB,我用这种方法计算最自由的窗格:

private int getFreerColumnIndex() {
    if(columns.isEmpty())
        return -1;

    int columnIndex = 0;
    int minHeight = 0;
    for(int i = 0; i < columns.size(); i++) {
        int height = 0;
        for(Node n : columns.get(i).getChildren()) {
            height += n.getBoundsInLocal().getHeight();
        }

        if(i == 0) {
            minHeight = height;
        } else if(height < minHeight) {
            minHeight = height;
            columnIndex = i;
        }

        if(height == 0)
            break;
    }

    return columnIndex;
}

此方法仅在我添加1个元素时才有效。但是如果我当时添加更多元素:

for (int i = 0; i < 10; i++) {
    SomeNode r1 = new SomeNode ();
    myPane.addElement(r1);
}

方法getFreerColumnIndex返回相同的索引。这是因为新节点在本地还没有高度 所以这一行:

height += n.getBoundsInLocal().getHeight(); 

将使用新节点返回0

任何人都知道如何获得节点的高度?


额外:

SomeNode Node

的延伸

myPane上的方法addElement():

public void addElement(final Node element) {
     index = getFreerColumnIndex();
     columns.get(index).getChildren().add(element);
}

额外2:

假设我们有3个vbox: 之前:

 A      B      C
 |      |      |
        |      |
        |

运行:

for (int i = 0; i < 10; i++) {
    SomeNode r1 = new SomeNode ();
    myPane.addElement(r1);                      
}

后:

 A      B      C
 |      |      |
 |      |      |
 |      |
 |
 |
 |
 |
 |
 |
 |
 |

正确

 A      B      C
 |      |      |
 |      |      |
 |      |      |
 |      |      |
 |      |      |
 |

| =某个节点

1 个答案:

答案 0 :(得分:18)

您需要做的是:

  1. 创建要放置在VBox中的节点。
  2. 将它们添加到某个场景(它可能只是一个未附加到舞台但与主场景具有相同CSS规则的新虚拟场景)。
  3. 在每个节点(或虚拟场景根)上调用applyCss()layout()
  4. 测量每个节点的布局范围。
  5. 根据布局算法将节点添加到真实场景中的VBox。
  6. 相关

    要了解如何衡量节点的大小,请参阅以下答案:

    背景

    JavaFX布局计算通过应用CSS和布局传递来工作。通常这是作为脉冲的一部分发生的(内部JavaFX系统中的一种自动60fps刻度,它检查场景中需要应用新css或布局的任何脏对象)。在大多数情况下,您只需指定场景所需的更改,并让自动脉冲布局机制在此时处理布局;这样做是非常有效的,因为它意味着脉冲之间的任何变化都是批量的,你不需要手动触发布局传递。但是,当您需要在布局发生之前(例如在您的情况下)实际获取大小时,您需要在尝试查询节点的高度和宽度范围之前手动触发CSS应用程序和布局传递。 / p>

    文档

    不幸的是,node.applyCSS()方法的详细Java 8u20 Javadoc目前已被破坏,因此我将重现此处Javadoc代码中的示例,因此您可以在上下文中查看建议的用法。对于下一个Java功能版本(8u40),损坏的javadoc作为RT-38330 Javadoc is missing for several methods of the Node class的一部分被修复,因此在该版本中,您将能够在JavaFX javadoc中找到以下文本:

      

    如果需要,请将样式应用于此节点及其子节点(如果有)。这种方法通常不需要   可以直接调用,但可以与layout()一起使用,以便在之前调整节点大小   下一个脉冲,或者如果场景不在舞台中。

         

    如果节点的场景不为空,则无论如何都将CSS应用于此节点   该Node的CSS状态是否干净。从最顶层的父级应用CSS样式   这个节点的CSS状态不是clean,这可能会影响其他节点的样式。   如果Node不在场景中,则此方法为无操作。场景不必处于舞台中。

         

    此方法不会调用layout()方法。通常,呼叫者将使用   遵循操作顺序。

    parentNode.applyCss();
    parentNode.layout();
    
         

    作为更完整的示例,以下代码使用applyCss()layout()来查找   显示了舞台前Button的宽度和高度。如果要求拨打applyCss()   或拨打layout()的电话已被注释掉,拨打getWidth()getHeight()   将返回零(直到显示舞台后的某个时间)。

    public void start(Stage stage) throws Exception {
       Group root = new Group();
       Scene scene = new Scene(root);
    
       Button button = new Button("Hello World");
       root.getChildren().add(button);
    
       root.applyCss();
       root.layout();
    
       double width = button.getWidth();
       double height = button.getHeight();
    
       System.out.println(width + ", " + height);
    
       stage.setScene(scene);
       stage.show();
    }
    

    替代

    这里的另一个选项是覆盖父节点的layoutChildren()方法,该方法是在布局传递期间调用以布置此父节点中的子节点。&#34;。在这样做时,可能还需要覆盖computePrefHeight()的方法以及prefWidth和min&amp; amp;的其他计算方法。最大高度和宽度。使用这种方法的详细描述很复杂,超出了本答案的范围。