简体   繁体   中英

Why aren't my CSS borders showing up in JavaFX gui?

I'm trying to show walls on the GUI (fxml) with CSS borders using .getStyleClass().add() but they're not showing up.

I'm using a switch that adds the corresponding style classes to the cells.

The Java code:

private StackPane createCell(int row, int col) {
    var cell = new StackPane();

    cell.getStyleClass().add("cell");
    cell.getStyleClass().add((row + col) % 2 == 0 ? "light": "dark");

    for (var i = 0; i < 2; i++) {
        var pieceView = new ImageView(pieceImages[i]);
        pieceView.visibleProperty().bind(createBindingForPieceAtPosition(i, row, col));
        cell.getChildren().add(pieceView);
    }

    var wallsInDirections = state.checkAllWalls(new Position(row, col));
    for (var direction : wallsInDirections) {
        switch (direction) {
            case UP -> cell.getStyleClass().add("topwall");
            case RIGHT -> cell.getStyleClass().add("rightwall");
            case DOWN -> cell.getStyleClass().add("bottomwall");
            case LEFT -> cell.getStyleClass().add("leftwall");
        }
    }
    return cell;
}

The CSS code:

.cell.light {
    -fx-background-color: white;
}

.cell.dark {
    -fx-background-color: #F6F6F6;
}

.cell.light:hover, .cell.dark:hover {
    -fx-background-color: #FAFA33;
}

.topwall {
    border-top: solid black;
}

.rightwall {
    border-right: solid black;
}

.bottomwall {
    border-bottom: solid black;
}

.leftwall {
    border-left: solid black;
}

Pic of the GUI afterwards: result

The properties border-top , border-right , etc. are not valid JavaFX CSS properties.

Referring to the documentation , you set the border using the properties

selector {
    -fx-border-color: color ;
    -fx-border-width: width ;
}

where color and width are either a single value (of type paint and size, respectively) or four values separated by spaces, representing the top, right, bottom, and left borders.

It should also be noted that borders are not typically used this way in JavaFX. The more usual approach is to use "nested backgrounds", where you would do something like this to define a border of width 5 around all four sides:

.cell.light {
    -fx-background: white;
}
.cell.dark {
    -fx-background: #f6f6f6;
}
.cell {
    -fx-background-color: black, -fx-background;
    -fx-background-insets: 0, 5;
}

This works by painting two backgrounds, one over the other. The first is black, with no insets; the second is defined by the "looked-up color" -fx-background , with an inset of 5 pixels on all sides.

My understanding (though I have no direct evidence of this) is that the nested background approach performs better than using explicit borders.

Unfortunately, doing this entirely in an external CSS sheet is very verbose, as you have to handle all 16 possibilities individually (unless I am missing a clever trick):

.cell.light {
    -fx-background: white;
}
.cell.dark {
    -fx-background: #f6f6f6;
}
.cell {
    -fx-background-color: black, -fx-background;
    -fx-background-insets: 0, 0;
}


.cell.topwall {
    -fx-background-insets: 0, 5 0 0 0;
}
.cell.rightwall {
    -fx-background-insets: 0, 0 5 0 0;
}
.cell.bottomwall {
    -fx-background-insets: 0, 0 0 5 0;
}
.cell.leftwall {
    -fx-background-insets: 0, 0 0 0 5;
}
.cell.topwall.rightwall {
    -fx-background-insets: 0, 5 5 0 0;
}
.cell.topwall.bottomwall {
    -fx-background-insets: 0, 5 0 5 0;
}
.cell.topwall.leftwall {
    -fx-background-insets: 0, 5 0 0 5;
}
.cell.rightwall.bottomwall {
    -fx-background-insets: 0, 0 5 5 0;
}
.cell.rightwall.leftwall {
    -fx-background-insets: 0, 0 5 0 5;
}
.cell.bottomwall.leftwall {
    -fx-background-insets: 0, 0 0 5 5;
}
.cell.topwall.rightwall.bottomwall {
    -fx-background-insets: 0, 5 5 5 0;
}
.cell.topwall.bottomwall.leftwall {
    -fx-background-insets: 0, 5 0 5 5;
}
.cell.topwall.rightwall.leftwall {
    -fx-background-insets: 0, 5 5 0 5;
}
.cell.rightwall.bottomwall.leftwall {
    -fx-background-insets: 0, 0 5 5 5;
}
.cell.topwall.rightwall.bottomwall.leftwall {
    -fx-background-insets: 0, 5;
}

(using -fx-border-* is no better).

It may be easier to set the insets programmatically as inline styles:

.cell.light {
    -fx-background: white;
}
.cell.dark {
    -fx-background: #f6f6f6;
}
.cell {
    -fx-background-color: black, -fx-background;
    -fx-background-insets: 0, 0;
}

and then

int top, right, bottom, left ;
top=right=bottom=left=0 ;
var wallsInDirections = state.checkAllWalls(new Position(row, col));
for (var direction : wallsInDirections) {
    switch (direction) {
        case UP -> top=5;
        case RIGHT -> right=5;
        case DOWN -> bottom=5;
        case LEFT -> left=5;
    }
}

cell.setStyle(String.format("-fx-background-insets: %d %d %d %d;", top, right, bottom, left));

Edited my CSS like this:

.topwall {
    -fx-border-style: solid hidden hidden hidden ;
    -fx-border-color: black;
    -fx-border-width: 5;
}

.rightwall {
    -fx-border-style: hidden solid hidden hidden;
    -fx-border-color: black;
    -fx-border-width: 5;
}

.bottomwall {
    -fx-border-style: hidden hidden solid hidden;
    -fx-border-color: black;
    -fx-border-width: 5;
}

.leftwall {
    -fx-border-style: hidden hidden hidden solid;
    -fx-border-color: black;
    -fx-border-width: 5;
}

and now they show up, but it displays only 1 border on each cell.

Result

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM