FX My Life IX: A Line In The Sand

Blake
4 min readMay 4, 2021

So, we want to declare a winner. Traditionally this is done by slashing a giant line through the grid, with the loser running to momma crying.

Or maybe you grew up differently.

Now, you can’t just draw a line because of course you can’t. That would be too easy. Think of it this way: FX container nodes typically describe the way its child nodes won’t run into each other. Like an HBox says, “place ’em side by side” and a FlowPane says “place ’em one after the other till you run out of space along that dimension, and then wrap.”

So, while we can easily create a line and set its dimensions:

line.setStartX(0);
line.setStartY(0);
line.setEndX(board.getWidth());
line.setEndY(board.getHeight());

If we just cram that into the board, we’ll get something like this:

You could do better with a crayon.

(Ignore the fact that the line isn’t even the right angle. One thing at a time.) We’ll get something similar if we try to cram it into the owning FlowPane.

So, what we really need is a place to put our line that, well, isn’t anything we’ve set up already. SceneBuilder has us covered. If we right-click on our FlowPane in SceneBuilder (or any control) there will be an option labeled “Wrap In” which will list all of our container controls.

Do this with FlowPane and click on Group, and our FlowPane will look like this:

Group Hug!

I gave this new group an ID of outerGroup and now:

if(gameOver) {
System.out.println("GAME OVER! " + winner + " WINS!");

var cw = board.getWidth() / 3;
var ch = board.getHeight() / 3;

outerGroup.getChildren().add(line);
line.setStartX(0);
line.setStartY(0);
line.setEndX(board.getWidth());
line.setEndY(board.getHeight());
}

Give us:

Now we can worry about putting the line in the right place and giving it some style. Style first.

The classic way of doing this is to just set the line’s property:

line.setStrokeWidth(5);
line.setStroke(Color.RED);

This is not bad:

But I feel like we should use CSS. According to the docs, a line has all the same attributes as a node (not interesting) and a shape (more interesting). But as always, one wonders where to put these things. I started by trying .line:

.line {
-fx-fill: green;
-fx-smooth: false;
-fx-stroke-width: 8;
}

And was denied the glory that is rightfully mine. Well, fine. Let’s force the issue by applying the line style directly:

line.getStyleClass().add("line");

Hmmm. The stroke width seems to have “took”. But not the green color nor the “rough”. IntelliJ does this cool thing where it tells you all the defined -fx CSS attributes when you’re in your CSS file. Just type -fx and hit Ctrl+Space and you’ll see a plethora.

I tried a bunch:

.line {
-fx-fill: green;
-fx-color: red;
-fx-stroke-color: yellow;
-fx-stroke: blue;
-fx-smooth: false;
-fx-stroke-width: 12;
}

It turns out -fx-stroke was the winner, actually changing the line to blue. Knowing that only:

.line {
-fx-stroke: red;
-fx-stroke-width: 12;
}

worked, you’d think it’d be easy to find the others. Well, stroke and stroke-width are in the docs, so let’s figure smooth didn’t work for some other reason.

After a fair amount of searching around, I could only find one more thing that worked. This is not definitive, but for now the CSS looks like this:

.line {
-fx-stroke: red;
-fx-stroke-width: 8;
-fx-stroke-line-cap: round;
}

From what I can tell, though, our issues aren’t with CSS, but with lines themselves, which don’t seem to use the other properties.

Next, we’ll work on the logic portion, admin and so on to get to a working tic-tac-toe game.

--

--

Blake
0 Followers

I am a poor, wayfaring stranger, traveling through this world of woe.