Ticker Tackor Soldier Spy
All your fields can be declared private. There is really no need to expose these more than necessary.

@FXML private Label systemOut;
@FXML private GridPane gridPane;
private final static int ROWS = 3;
private final static int COLUMNS = 3;
private int[][] grid;
private boolean turn;




Your initialize and newGame methods looks very much the same to me, you could change your initialize to:

public void initialize(URL location, ResourceBundle resources) {
    newGame(null);
}




public void WhoWon(int x, int[] zone){
    if (zone[x] == 3){
        systemOut.setText("Os won!");
    }else if (zone[x] == 30){
        systemOut.setText("Xs won!");
    }
}


@barq is correct that the method name can be improved, and that passing a single int value to this method should be enough, which can make it:

public void declareWinner(int value) {
    if (value == 3) {
        systemOut.setText("Os won!");
    } else if (value == 30) {
        systemOut.setText("Xs won!");
    }
}


However, these magic numbers 3 and 30 really needs to be fixed. I'd recommend an enum:

public enum Player {
    X, O;
}


And then use a Player[][] instead of int[][]. and a Player turn instead of boolean.



Your win-check approach is a bit... more complicated than necessary. You begin with:

for (int y = 0; y &lt; 3; y++) {
    for (int x = 0; x &lt; 3; x++) {
        zone[zoneNumber] = grid[y][x];
        zoneNumber++;
    }
}


But in reality, there is no need to transform all the positions to a number, instead you can access the 2d array directly, like this:

for (int y = 0; y &lt; 3; y++) {
    if (zone[0][y] == zone[1][y] &amp;&amp; zone[0][y] == zone[2][y]) {
        declareWinner(zone[0][y]);
    }
}
for (int x = 0; x &lt; 3; x++) {
    if (zone[x][0] == zone[x][1] &amp;&amp; zone[x][0] == zone[x][2]) {
        declareWinner(zone[x][0]);
    }
}
if (zone[0][0] == zone[1][1] &amp;&amp; zone[0][0] == zone[2][2]) {
    declareWinner(zone[0][0]);
} else if (zone[2][0] == zone[1][1] &amp;&amp; zone[2][0] == zone[0][2]) {
    declareWinner(zone[2][0]);
}




In ButtonCell you are doing:

hoboChess.grid[y][x] = 3;


And violà, you have flipped x and y! In other places you are doing grid[x][y] but here we have grid[y][x]. Thanks to how Tic Tac Toe works, you won't see a difference, but it is still quite important to be consistent.

Also, when changing to using an enum this can become

hoboChess.grid[x][y] = Player.X;


or

hoboChess.grid[x][y] = Player.O;




Overall it does look like you have improved over time. A little additional improvement I would recommend is to separate the game board and logic more from your Java FX controller class.

I would use one file for TicTacToeGame, containing the Player[][] array and who's turn it is, then I would use a method Player makeMove(int x, int y) that would place a mark at the specified position and return which player made the move (for the button to know what mark to set). This game logic class can be made entirely independent of your JavaFX controller, so that it can be easily used in a Java console application, a Swing application, or another framework. This is an important step and skill in programming, to be able to create re-usable classes.