Search code examples
cssjavafxfxml

Problems with setting TableColumn width in FXML using CSS


Here is my .fxml code:

<TableColumn id="tableColumnVertical" text="">
    <graphic>
        <VBox>
            <Label text="text"/>
        </VBox>
    </graphic>
</TableColumn>

Here I have simplified .css code:

#tableColumnVertical {
    -fx-background-color: Lime;
    -fx-min-width: 40;
    -fx-max-width: 40;
}

This doesn't set width of TableColumn but sets background. Why?

I can use this code:

<TableColumn id="tableColumnVertical" text="" minWidth="40" maxWidth="40">

and it works. Why inline works and .css does not?

While writing this post I tried adding -fx-pref-width: 40; to .css and now it also works.

1) I would like know why inline works and .css does not (while background-color works)? Why after adding prefWidth it started to work?

2) Can I use both fx:id and id?

3) Also, in some SO answers I saw people advice to use styleClass to set style. When should I use styleClass?

Edit:

a TableColumn also contains the necessary properties to:

  • Be resized (using minWidth/prefWidth/maxWidth and width properties)

https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TableColumn.html

Not sure if this is accurate, but I decided to post this edit.


Solution

    1. The -fx-pref-width is setting the property of the TableColumnHeader (same for -fx-min-width, see below). Setting this property via CSS is buggy: JDK-8087822.
    2. You can use both fx:id and id. If you only set fx:id it will also be used for the id. If you set both, the id is used for CSS and the fx:id is used for injecting the instance into a controller.
    3. You would add a style class if you want to style many nodes the same way.

    Note: The following mostly deals with implementation details for JavaFX 11.0.1 (at least, I couldn't find documentation).

    The problem is the difference between TableColumnBase.minWidth and Region.minWidth. The former is not styleable from CSS because it is not a StyleableProperty. The latter is and it is that property that defines the -fx-min-width CSS property.

    When you do:

    <TableColumn id="tableColumnVertical" text="" minWidth="40" maxWidth="40">
    

    You are setting the minWidth property of the TableColumn using a property setter. It is not analogous to setting the CSS property.

    However, the JavaFX CSS Reference Guide does document that TableColumn is part of the substructure of a TableView. This would seem to indicate you can style the column via CSS. But again, non of the properties are actually styleable; the getCssMetaData() method returns Collections.emptyList().

    TableColumnBase does implement Styleable (where getCssMetaData() comes from) which means it has the following method: getStyleableNode(). The TableColumn implementation of this method, once the TableView has been displayed, returns an instance of TableColumnHeader. What this means is any CSS applied to the TableColumn is actually applied to the TableColumnHeader. It is this latter class that extends Region and thus has the styleable minWidth property. And from some testing the minWidth property of the TableColumnHeader instance is set as expected.

    The problem appears to be that the minWidth of the TableColumnHeader has no affect on the TableColumn. The implementation only takes TableColumn.minWidth into account. And this unfortunately means you won't be able to set the minWidth of the TableColumn from CSS.

    This behavior might be a bug.