Holen Sie sich die Höhe eines Knotens in JavaFX (generieren Sie einen Layout-Pass)

Lesezeit: 6 Minuten

Holen Sie sich die Hohe eines Knotens in JavaFX generieren
Ikone

Wie man die Höhe oder bevorzugte Höhe eines Knotens in JavaFX erhält, habe ich 3 VBox und ich möchte dem freieren Panel Knoten hinzufügen, Beispiel:

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

In diesem Fall ist die freiere die VBoxBich berechne den freieren Bereich mit dieser Methode:

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;
}

Diese Methode funktioniert nur, wenn ich jeweils 1 Element hinzufüge. Aber wenn ich gleichzeitig weitere Elemente hinzufüge:

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

die Methode getFreerColumnIndex denselben Index zurückgeben. Dies liegt daran, dass die neuen Knoten noch keine lokale Höhe haben.
Also diese Zeile:

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

wird zurückkehren 0 mit den neuen Knoten.

Weiß jemand, wie man die Höhe eines Knotens ermittelt?


Extra:

SomeNode erstreckt sich von Node

Methode addElement() bei myPane:

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

Ergänzung 2:

Angenommen, wir haben 3 vbox: Vorher:

 A      B      C
 |      |      |
        |      |
        |

Laufen:

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

Nach dem:

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

Richtig:

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

| = Irgendein Knoten

Holen Sie sich die Hohe eines Knotens in JavaFX generieren
Juwelsee

Was Sie tun müssen, ist:

  1. Erstellen Sie die Knoten, die in den VBoxen platziert werden sollen.
  2. Fügen Sie sie einer Szene hinzu (es kann einfach eine neue Dummy-Szene sein, die nicht mit der Bühne verbunden ist, aber dieselben CSS-Regeln wie Ihre Hauptszene hat).
  3. Anruf applyCss() und layout() auf jedem der Knoten (oder der Dummy-Szenenwurzel).
  4. Messen Sie die Layoutgrenzen jedes der Knoten.
  5. Fügen Sie die Knoten gemäß Ihrem Layoutalgorithmus zu den VBoxen in Ihrer realen Szene hinzu.

Verwandt

Um herauszufinden, wie man die Größe eines Knotens misst, siehe die Antwort auf:

  • Wie berechnet man die Pixelbreite eines Strings in JavaFX?

Hintergrund

JavaFX-Layoutberechnungen funktionieren durch Anwenden von CSS und einem Layout-Pass. Normalerweise geschieht dies als Teil eines Pulses (eine Art automatischer 60-fps-Tick im internen JavaFX-System, das nach schmutzigen Objekten in der Szene sucht, auf die ein neues CSS oder Layout angewendet werden muss). In den meisten Fällen können Sie einfach die gewünschten Änderungen an der Szene angeben und den automatisierten Impuls-Layout-Mechanismus das Layout zu diesem Zeitpunkt handhaben lassen; Dies ist sehr effizient, da es bedeutet, dass alle Änderungen zwischen einem Impuls zusammengefasst werden und Sie Layout-Durchgänge nicht manuell auslösen müssen. Wenn Sie jedoch die Größe der Dinge tatsächlich ermitteln müssen, bevor das Layout erfolgt (wie in Ihrem Fall), müssen Sie die CSS-Anwendung und den Layoutdurchlauf manuell auslösen, bevor Sie versuchen, die Höhen- und Breitenausdehnungen des Knotens abzufragen.

Dokumentation

Leider ist die ausführliche Java 8u20 Javadoc für die node.applyCSS() -Methode ist derzeit defekt, daher reproduziere ich das Beispiel, das sich hier im Javadoc-Code befindet, damit Sie die empfohlene Verwendung im Kontext sehen können. Für das nächste Java-Feature-Release (8u40) wird das defekte Javadoc als Teil von behoben RT-38330 Javadoc fehlt für mehrere Methoden der Node-Klassesodass Sie mit dieser Version den folgenden Text in der JavaFX-Javadoc finden können:

Wenden Sie bei Bedarf Stile auf diesen Knoten und seine untergeordneten Elemente an, falls vorhanden. Diese Methode muss normalerweise nicht direkt aufgerufen werden, kann aber in Verbindung mit verwendet werden layout() um einen Knoten vor dem nächsten Impuls zu dimensionieren, oder wenn sich die Szene nicht in einer Stufe befindet.

Vorausgesetzt, dass die Szene des Knotens nicht null ist, wird CSS auf diesen Knoten angewendet, unabhängig davon, ob der CSS-Zustand dieses Knotens sauber ist. CSS-Stile werden vom obersten übergeordneten Knoten dieses Knotens angewendet, dessen CSS-Status nicht sauber ist, was sich auf den Stil anderer Knoten auswirken kann. Diese Methode ist keine Operation, wenn sich der Knoten nicht in einer Szene befindet. Die Szene muss sich nicht in einer Bühne befinden.

Diese Methode ruft die nicht auf layout() Methode. Typischerweise verwendet der Aufrufer die folgende Abfolge von Operationen.

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

Als vollständigeres Beispiel wird der folgende Code verwendet applyCss() und layout() um die Breite und Höhe des Buttons zu finden, bevor die Bühne gezeigt wurde. Wenn entweder der Anruf an applyCss()
oder der Anruf bei layout() Auskommentiert ist, die Aufrufe an getWidth() und getHeight()
gibt Null zurück (bis einige Zeit nachdem die Bühne angezeigt wird).

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();
}

layout() vs. requestLayout()

Der Aufruf von layout() führt sofort einen Layoutdurchlauf durch.

Der Aufruf von requestLayout() führt in Zukunft einen Layoutdurchlauf durch:

Fordert einen Layoutdurchlauf an, bevor die nächste Szene gerendert wird. Dies wird asynchron gestapelt, um einmal pro „Impuls“ oder Frame der Animation zu geschehen.

RequestLayout() informiert also das System, dass ein Layout erfolgen muss, führt das Layout aber nicht sofort durch.

Normalerweise müssen Sie requestLayout() nicht direkt aufrufen, da das JavaFX-System meistens intern feststellen kann, dass ein Bereich der Szene schmutzig ist, und das Layout bei Bedarf automatisch ausführen muss.

Alternative

Die andere Option hier ist, die zu überschreiben layoutChildren() -Methode eines übergeordneten Knotens, die “während des Layoutdurchgangs aufgerufen wird, um die untergeordneten Elemente in diesem übergeordneten Element zu erstellen.”. Dabei kann es auch notwendig sein, Methoden to zu überschreiben computePrefHeight() sowie andere Berechnungsmethoden für prefWidth und minimale und maximale Höhe und Breite. Eine detaillierte Beschreibung der Verwendung dieses Ansatzes ist kompliziert und würde den Rahmen dieser Antwort sprengen.

  • sehr umfassende Antwort für neue Bienen, die das Wesentliche des Lernens erleichtert

    – Wiederholungsnull

    15. März 2018 um 14:56 Uhr

Holen Sie sich die Hohe eines Knotens in JavaFX generieren
silvalli

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import java.io.Closeable;

public class Sizing  extends Application {

  @Override
  public void start(Stage stage) {
    var label = new Label();
    var labelHeight = label.getHeight();
    System.out.println(labelHeight);

    try (var s = new SizingSandbox(label)) {
      labelHeight = label.getHeight();
    }

    System.out.println(labelHeight);
  }

  public static void main(String[] args)  { launch(args); }
}


class SizingSandbox extends Group  implements Closeable {

  public SizingSandbox(Node... nodes) {
    new Scene(this);
    getChildren().addAll(nodes);
    layItOut();
  }

  @Override
  public void close() {
    try {
      getChildren().removeAll();
    } catch (Exception e) { }
  }

  private void layItOut() {
    applyCss();
    layout();
  }
}

// output:
// 0.0
// 17.0

  • @jewelsea Danke!

    – silvalli

    17. Januar um 3:19

917000cookie-checkHolen Sie sich die Höhe eines Knotens in JavaFX (generieren Sie einen Layout-Pass)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy