Search code examples
javahibernatejavafxtablecolumn

TableColumn doesn't display values (JavaFX 11)


I made TableView with two columns - first assigned to a value from class from List imported from other TableView via selection model, second assigned to some value of the class. But second column still stays empty.

I'm setting up a TableView which contains Player's nickname (String) and his seat (int). I generated in main controll TableView which was generated from SQL table by Hibernate. Player's values imported from SQL table are annotaded by @Column, the value 'seat' has annotation @Transient. I tried to do this by methods found on stack but they're not working here.

Here is controller which contains the TableView:

public class SeatsController {
private ObservableList<Player> players;

@FXML private TableView<Player> playersTableSeats;
@FXML private TableColumn playerColumn;
@FXML private TableColumn<Player, String> seatColumn;

@FXML private TextField seatField;

public void initialize() {
    players = FXCollections.observableArrayList();
    playersTableSeats.setItems(players);
    seatColumn.setCellValueFactory(cellData -> new 
SimpleStringProperty(cellData.getValue().getSeat()+"", "seat"));
}

public void manageSeats(List<Player> list) {
    players.addAll(list);
}

@FXML
public void setSeat() {
    Player selectedPlayer = 
playersTableSeats.getSelectionModel().getSelectedItem();
    selectedPlayer.setSeat(Integer.parseInt(seatField.getText()));
    playersTableSeats.setItems(players);
    System.out.println(selectedPlayer.getSeat());
}
}

Part of FXML file (seats.fxml):

<TableView fx:id="playersTableSeats">
    <columns>
        <TableColumn fx:id="playerColumn" text="Nickname">
            <cellValueFactory>
                <PropertyValueFactory property="nickname"/>
            </cellValueFactory>
        </TableColumn>
        <TableColumn fx:id="seatColumn" text="Seat">
            <cellValueFactory>
                <PropertyValueFactory property="seat"/>
            </cellValueFactory>
        </TableColumn>
    </columns>
</TableView>
<HBox>
    <Label text="Set place:"></Label>
    <TextField fx:id="seatField"></TextField>
    <Button text="OK" onAction="#setSeat"></Button>
</HBox>

Class player:

@Entity
@Table(name = "Players")
@Getter
@Setter
public class Player {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;

@Column(name = "nickname")
private String nickname;

@Column(name = "chips")
private int chips;

@Column(name = "notes")
private String notes;

@Transient
private int seat;

[some values with @Transient]

public Player() {}

public Player(int id, String nickname, int chips, String notes) {
    this.id = id;
    this.nickname = nickname;
    this.chips = chips;
    this.notes = notes;
    seat = -1;
}
}

Getters and setters are default (created by lombok but don't care).

Start of this controller is caused by:

SeatsController seatsController = fxmlLoader.getController();
seatsController.manageSeats(selectedPlayers);

in main Controller after correct selection and click on the button 'Run!'.

https://i.sstatic.net/upned.png

I try to do something with seatColumn.setCellValueFactory([lambda]) and setCellValue([lambda]) but all of my attempts fail.


Solution

  • You use the wrong SimpleStringProperty constructor for the intended purpose:

    SimpleStringProperty​(Object bean, String name) only receives "metadata" about the property, but not doesn't actually initialize the value:

    • bean is the object containing the property
    • name is a string containing the name of the property

    Both are used to assign the properties of the same name for the property object.

    TableView doesn't do anything with those properties. It simply uses the value which is not assigned by the constructor used and therefore remains at the initial value of null.

    You could use

    seatColumn.setCellValueFactory(cellData -> new SimpleStringProperty(Integer.toString(cellData.getValue().getSeat())));
    

    However I recommend keeping the type of the property instead of converting to String:

    @FXML private TableColumn<Player, Number> seatColumn;
    
    seatColumn.setCellValueFactory(cellData -> new SimpleIntegerProperty(cellData.getValue().getSeat()));
    

    Initializing the cellValueFactory from the initialize method you should remove the creation of the factory from the fxml file, since just the factory assigned later is used by TableView.