获取JavaFX中节点的高度(生成布局遍历)

问题描述

您需要做的是:

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

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

    如何在JavaFX中计算字符串的像素宽度? 背景

    JavaFX布局计算通过应用CSS和布局传递来工作。通常,这是作为脉冲的一部分发生的(内部JavaFX系统中的一种自动60fps滴答,它检查场景中是否有脏物体需要应用新的CSS或布局)。在大多数情况下,您可以只指定要对场景进行的更改,然后由自动脉冲布局机制处理当时的布局。这样做非常有效,因为这意味着脉冲之间的任何更改都会被分批处理,并且您无需手动触发布局遍历。但是,当需要在布局发生之前实际获得事物的大小时(如您的情况),那么在尝试查询节点的高度和宽度范围之前,需要手动触发CSS应用程序和布局传递。

    文献资料

    不幸的是,该node.applyCSS()方法的详细Java 8u20 Javadoc当前已被破坏,因此我将在此处重现Javadoc代码中的示例,因此您可以在上下文中看到推荐的用法。对于下一个Java功能版本(8u40),已修复损坏的Javadoc,作为RT-38330的一部分,Node类的几种方法都缺少Javadoc,因此在该版本中,您将能够在JavaFX javadoc中找到以下文本:

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

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

    方法调用该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()父节点的方法,即“在布局传递期间调用以在此父节点中布局子级”。这样做时,computePrefHeight()对于prefWidth和min&max height&width的方法以及其他计算方法也可能需要覆盖。使用此方法的详细说明很复杂,超出了此答案的范围。

    解决方法

    如何在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
     |      |      |
            |      |
            |
    

    run:

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

    后:

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

    正确的:

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

    | =一些节点

猜你在找的技术问答相关文章

如何检查配对的蓝牙设备是打印机还是扫描仪(Android)
是否允许实体正文进行HTTP DELETE请求?
如何将ZipInputStream转换为InputStream?
java.util.logging Java 8中的变量
PowerMockito.doReturn返回null
Java中的RESTful调用
Swing / Java:如何正确使用getText和setText字符串
特殊字符和重音字符
Android Studio中的ndk.dir错误
错误“找不到主类”