Центрировать дочерние элементы в GridPane с помощью CSS

введите здесь описание изображения

У меня есть GridPane, заполненный ToggleButtons. Первая строка и столбец в этом GridPane содержит Text меток объектов.
Я не могу центрировать Text объектов с помощью ToggleButton, поэтому текст появляется посередине, используя css.
( Этот ответ показывает, как этого добиться с помощью GridPane.setHalignment(node, HPos.CENTER);).

MCVE при необходимости:

import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class GridTest extends Application {

    private static final int COLS = 5, ROWS = 3;

    @Override public void start(Stage stage) {
        Scene scene = new Scene(makeGrid());
        scene.getStylesheets().add(getClass().
                getResource("GridTest.css").toExternalForm());
        stage.setScene(scene);
        stage.show();
    }

    private Pane makeGrid() {

        GridPane grid = new GridPane();

        for(int rowIndex = 0; rowIndex < ROWS ; rowIndex++) {

            Node[] nodes = new Node[COLS];
            Node node;
            for(int colIndex = 0; colIndex < COLS ; colIndex++) {

                if (rowIndex == 0){ //col header;
                    String txt =  (colIndex == 0) ?
                            " " : String.valueOf(colIndex);
                    node = new Text(txt);
                }else if (colIndex == 0){//row header
                    node = new Text(String.valueOf(rowIndex));
                }else {
                    node= new ToggleButton();
                }
                nodes[colIndex]= node;
            }
            grid.addRow(rowIndex, nodes);
        }
        return grid;
    }

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

CSS:

Text{
    -fx-text-alignment: center;
}

GridPane {
    -fx-hpos:center ;
    -fx-hgap: 5;
    -fx-vgap: 5;
    -fx-padding:10;  
}

ToggleButton {  
    -fx-pref-width:30;
}

person c0der    schedule 22.05.2018    source источник
comment
См. документы: Примечание. : в случае одной строки текста, где ширина узла определяется шириной текста, настройка выравнивания не действует. Вы можете использовать метку и установить alignment (не textAlignment) по центру в CSS, но вам все равно нужно настроить панель сетки в Java, чтобы позволить метке увеличиваться, чтобы заполнить ячейку панели сетки. Как правило, вы должны использовать JavaFX CSS для управления стилем, а не макетом (хотя граница между ними иногда размыта).   -  person James_D    schedule 22.05.2018
comment
@James_D спасибо за быстрый ответ. Я знаю об этом. Я видел это в некоторых ваших ответах здесь. В этом случае необходимо центрировать объект Text в столбцах Gridpane (не центрировать текст в элементе управления Text). Я могу легко продемонстрировать решение, используя GridPane.setHalignment(node, HPos.CENTER) . Я ищу решение CSS.   -  person c0der    schedule 22.05.2018
comment
Как я уже сказал, это неправильное использование CSS в JavaFX. Не пытайтесь использовать CSS для макета: для этого вам следует использовать либо Java, либо FXML.   -  person James_D    schedule 22.05.2018
comment
@James_D Я понимаю твою точку зрения. Разве -fx-hpos:center ; не для этого?   -  person c0der    schedule 22.05.2018
comment
Я не знаю об этом свойстве: оно не указано в документы CSS, насколько я могу судить. Если бы он что-то делал, я бы предположил, что он устанавливает положение всего содержимого панели сетки в пространстве, выделенном для панели сетки его родителем, если это пространство больше, чем пространство, необходимое панели сетки.   -  person James_D    schedule 22.05.2018
comment
Он отображается под некоторыми Panes , Labeled и некоторые другие.   -  person c0der    schedule 22.05.2018
comment
Это документация по JavaFX 1.x. Это устарело около 8 лет. Его нет в текущая версия (JavaFX 10). Он заменен на -fx-alignment (который устанавливает как горизонтальное, так и вертикальное выравнивание) и делает то, что я описал (устанавливает выравнивание всего содержимого панели, а не выравнивание в каждой ячейке панели сетки).   -  person James_D    schedule 22.05.2018
comment
Text узлы не изменяют размер. Вы также не можете установить свойства static через css. Это означает, что ваш единственный вариант только с css — выравнивание по центру каждого дочернего элемента с использованием fx-alignment: center; на GridPane. Кроме этого вы ничего не можете сделать, если только вы не замените узлы Text на Labels и не увеличите максимальный размер до достаточно больших значений, а затем не отцентрируете текст Label...   -  person fabian    schedule 22.05.2018
comment
Я думаю, что даже если вы установите максимальный размер метки, она на самом деле не увеличится до размера ячейки без GridPane.setFillWidth(label, true) (я не верю, что это значение по умолчанию), и, как уже было сказано, нет способа установить статическое свойство в CSS.   -  person James_D    schedule 23.05.2018


Ответы (1)


Основываясь на комментариях, опубликованных @James_D и @fabian, и на предыдущих ответах, есть два варианта центрирования текстовых меток.
Один вариант, указанный в вопросе, не использует css. Требуется небольшая модификация makeGrid:

//see: https://stackoverflow.com/a/35438985/3992939
GridPane.setHalignment(node, HPos.CENTER);  //added line
nodes[colIndex]= node;

Это решение не меняет (без изменения размера) Text. Он просто центрирует его в родительском столбце GridPane.

Другой вариант включает изменение меток Text на Labels :

private Pane makeGrid() {

    GridPane grid = new GridPane();
    for(int rowIndex = 0; rowIndex < ROWS ; rowIndex++) {

        Node[] nodes = new Node[COLS];
        Node node;
        for(int colIndex = 0; colIndex < COLS ; colIndex++) {
            if (rowIndex == 0){ //col header;
                String txt =  (colIndex == 0) ? " " : String.valueOf(colIndex);
                node = new Label(txt);                      //** changed 
            }else if (colIndex == 0){//row header
                node = new Label(String.valueOf(rowIndex)); //** changed 
            }else {
                node= new ToggleButton();
            }
            nodes[colIndex]= node;
        }
        grid.addRow(rowIndex, nodes);
    }
    return grid;
}

И используя css (или дополнительный код), чтобы установить максимальную ширину метки и центрировать текст:

GridPane .label{
    -fx-alignment: center;
    -fx-max-width: Infinity;
}

GridPane {
    -fx-hgap: 5;
    -fx-vgap: 5;
    -fx-padding:10;  
}

ToggleButton {  
    -fx-pref-width:30;
}

введите здесь описание изображения

person c0der    schedule 23.05.2018