GridPane не дает метки достаточно места при использовании столбцов с процентной шириной - PullRequest
2 голосов
/ 08 апреля 2019

Код ниже генерирует этот снимок экрана:

Label not fitting

Метка под 2-й колонкой не хочет правильно требовать дополнительное пространство, когда это необходимобыть завернутым.Это происходит только тогда, когда столбцы используют процентную ширину - в документах говорится, что в этом случае будут игнорироваться все другие свойства, включая hgrow и т. Д., Но не упоминается, что это также повлияет на работу строк ... но этоПохоже, что это так.

Кто-нибудь получил обходной путь или может сказать мне, что я делаю неправильно?Все, что я хочу, - это отобразить 3 изображения с метками неизвестного размера, расположенными под ними, которые хорошо разнесены и выровнены и имеют одинаковый размер ... Примерно так:

Properly reflowed labels

Выше сделано с пользовательским элементом управления, предварительно названным "BetterGridPane" ...

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;

public class TestLabelWrap extends Application {

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

  @Override
  public void start(Stage primaryStage) throws Exception {
    GridPane root = new GridPane();

    root.add(new ListView(FXCollections.observableArrayList("1", "2", "3")), 0, 0);
    root.add(new ListView(FXCollections.observableArrayList("1", "2", "3")), 1, 0);
    root.add(new ListView(FXCollections.observableArrayList("1", "2", "3")), 2, 0);

    root.add(new Label("Value A"), 0, 1);
    root.add(new Label("The value for this porperty is so large it wraps, The value for this porperty is so large it wraps") {{
      setWrapText(true);
    }}, 1, 1);
    root.add(new Label("Value C"), 2, 1);

    root.getColumnConstraints().add(new ColumnConstraints() {{ setPercentWidth(33.33); }});
    root.getColumnConstraints().add(new ColumnConstraints() {{ setPercentWidth(33.33); }});
    root.getColumnConstraints().add(new ColumnConstraints() {{ setPercentWidth(33.33); }});

    root.getRowConstraints().add(new RowConstraints() {{ setVgrow(Priority.NEVER); }});
    root.getRowConstraints().add(new RowConstraints() {{ setVgrow(Priority.ALWAYS); }});

    primaryStage.setScene(new Scene(root));
    primaryStage.show();
  }
}

1 Ответ

3 голосов
/ 09 апреля 2019

Установка wrapText на true на самом деле кажется достаточной.Вы можете увидеть это, просто увеличив высоту своего окна и наблюдая, как текст начинает переноситься (уменьшая ширину окна по мере необходимости).Кажется, проблема в GridPane, и это начальный размер расчета - он растет горизонтально, чтобы вместить Label, но не вертикально.Одно из исправлений - просто дать Scene, GridPane или Label явную (предпочтительную) ширину, оставляя высоту для вычисления.

  • new Scene(root, someWidth, -1)
  • root.setPrefWidth(someWidth)
  • label.setPrefWidth(someWidth) + label.setMaxWidth(Double.MAX_VALUE)

Однако, хотя Javadoc ColumnConstraints.percentWidth говорит:

Если установленоЕсли значение больше 0, размер столбца будет изменен на этот процент от доступной ширины области сетки, а другие ограничения размера (minWidth, prefWidth, maxWidth, hgrow) будут игнорироваться.

[min|pref|max]Widthне игнорируется при расчете предпочтительного размера .Поскольку у вас есть изображения известной и одинаковой ширины, вы должны иметь возможность установить предпочтительную ширину каждого ограничения, которая будет немного больше ширины изображения.Вот пример (с использованием OpenJDK 12 и OpenJFX 12):

import java.util.stream.Stream;
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;

public class Main extends Application {

    private static ColumnConstraints[] createColumnConstraints() {
        return Stream.generate(() -> {
            var constraint = new ColumnConstraints();
            constraint.setHalignment(HPos.CENTER);
            constraint.setPercentWidth(100.0 / 3.0);
            constraint.setPrefWidth(225.0); // SET PREF WIDTH
            return constraint;
        }).limit(3).toArray(ColumnConstraints[]::new);
    }

    private static Rectangle[] createRectangles() {
        return Stream.generate(() -> new Rectangle(100.0, 150.0)).limit(3).toArray(Rectangle[]::new);
    }

    private static Label[] createLabels(String... texts) {
        return Stream.of(texts).map(text -> {
            var label = new Label(text);
            label.setWrapText(true);
            label.setTextAlignment(TextAlignment.CENTER);
            return label;
        }).toArray(Label[]::new);
    }

    @Override
    public void start(Stage primaryStage) {
        var root = new GridPane();
        root.setGridLinesVisible(true); // FOR VISUAL CLARITY
        root.setHgap(10.0);
        root.setVgap(10.0);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(20.0));
        root.getColumnConstraints().addAll(createColumnConstraints());

        root.addRow(0, createRectangles());
        root.addRow(1, createLabels("Label A", "This is long text. ".repeat(10), "Label C"));

        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

}

Что приводит к:

screenshot of UI created by example code


Предположение:

Поскольку вы используете new Scene(root), это означает, что Scene будет изменять размер до предпочтительного размера его содержимого.Это в основном дает корню свободное правление, чтобы расти настолько большим, насколько это необходимо.Как описано в GridPane:

По умолчанию размер строк и столбцов будет соответствовать их содержанию;столбец будет достаточно широким, чтобы вместить самого широкого дочернего элемента, а ряд достаточно высоким, чтобы вместить самого высокого дочернего элемента.

При использовании percentWidth ширина каждого столбца фактически не имеетверхняя граница;они вырастут, чтобы соответствовать широкому ребенку.Кроме того, поскольку каждый столбец использует percentWidth, по мере роста все они растут.

Это означает, что Label s имеет практически неограниченное пространство для горизонтального роста, что означает, что предпочтительная высота Label рассчитывается как одна строка текста;зачем оборачивать, когда у вас бесконечная ширина?Из-за этого строка, к которой принадлежат Label, увеличивается только по вертикали, чтобы вместить одну строку текста.Нет места для переноса текста.

...