1

enter image description here

I have a GridPane populated with ToggleButtons. First row and column in that GridPane holds Text object labels.
I am unable to center the Text objects with the ToggleButtons so the text appears in the middle, using css.
(This answer shows how to achieve it by using GridPane.setHalignment(node, HPos.CENTER);).

MCVE if needed :

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;
}
c0der
  • 18,467
  • 6
  • 33
  • 65
  • 1
    See [docs](https://docs.oracle.com/javase/9/docs/api/javafx/scene/text/Text.html#textAlignmentProperty): "Note: In the case of a single line of text, where the width of the node is determined by the width of the text, the alignment setting has no effect.". You can use a label and set the `alignment` (not the `textAlignment`) to center in CSS, but you will still need to configure the grid pane in Java to allow the label to grow to fill the grid pane cell. Typically, you should use JavaFX CSS to manage *style*, not *layout* (though the boundary between the two is blurred sometimes). – James_D May 22 '18 at 15:00
  • @James_D thanks for your quick response. I am aware of it. I saw it in some of your answers here. In this case the need is center the `Text` object within the `Gridpane` columns (not to center the text within the `Text` control). I can easily demonstrate a solution using `GridPane.setHalignment(node, HPos.CENTER)` . I am looking for a CSS solution. – c0der May 22 '18 at 15:09
  • 1
    As I said, this is a misuse of CSS in JavaFX. Don't try to use CSS for layout: you should use either Java or FXML for that. – James_D May 22 '18 at 15:10
  • @James_D I see your point. Isn't that what `-fx-hpos:center ;` is for ? – c0der May 22 '18 at 15:13
  • 1
    I'm not aware of that property: it isn't listed in the [CSS docs](https://docs.oracle.com/javase/9/docs/api/javafx/scene/doc-files/cssref.html) as far as I can tell. If it did anything, I would imagine it set the position of the entire grid pane's content within the space allocated to the grid pane by its parent, should that space be larger than the space the grid pane needed. – James_D May 22 '18 at 15:16
  • It shows under some [Panes](https://docs.oracle.com/cd/E17802_01/javafx/javafx/1.3/docs/api/javafx.scene/doc-files/cssref.html#vbox) , Labeled and a few more. – c0der May 22 '18 at 15:33
  • 1
    That's JavaFX 1.x documentation. That's been deprecated for about 8 years. It is not present in the [current version](https://docs.oracle.com/javase/10/docs/api/javafx/scene/doc-files/cssref.html#vbox) (JavaFX 10). It's superseded by `-fx-alignment` (which sets both the horizontal and vertical alignment), and does as I described (sets the alignment of the entire content of the pane, not the alignment within each cell of the grid pane). – James_D May 22 '18 at 15:35
  • 1
    `Text` nodes are non resizable. You cannot set `static` properties via css either. This means your only option with css only is center aligning every child using `fx-alignment: center;` on the `GridPane`. Other than that you cannot anything, unless you replace the `Text` nodes with `Label`s and increase the max size to large enough values and then centering the `Label` text... – fabian May 22 '18 at 18:06
  • I think even if you set the max size of a label, it won't actually grow to the size of the cell without `GridPane.setFillWidth(label, true)` (I don't believe that's the default), and, as pointed out, there's no way to set a static property in CSS. – James_D May 22 '18 at 22:06

1 Answers1

3

Based on the comments posted by @ James_D and @fabian and previous answers there are two options to get the text labels centered.
One option, as posted in the question, does not use css. It requires slight modification of the makeGrid:

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

This solutions does not change the (non resizable) Text. It simple centers it within its GridPane parent column.

The other option involves changing the Text lables to 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;
}

And using css (or additional code) to set the label's width to maximum and center the text :

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

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

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

enter image description here

c0der
  • 18,467
  • 6
  • 33
  • 65