Skip to content

Instantly share code, notes, and snippets.

@dmolesUC
Created December 19, 2017 19:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmolesUC/03eb008dcdb3ea40a9777f1407544be8 to your computer and use it in GitHub Desktop.
Save dmolesUC/03eb008dcdb3ea40a9777f1407544be8 to your computer and use it in GitHub Desktop.
Displaying JavaFX TableView row number in a column
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class IndexColumnDemo extends Application {
@Override
public void start(Stage stage) {
stage.setTitle("Table height example");
TableView<String> table = new TableView<>(FXCollections.observableArrayList(
"Stacey", "Kristy", "Mary Anne", "Claudia"
));
TableColumn<String, Integer> indexColumn = new TableColumn<>();
indexColumn.setCellFactory(col -> {
TableCell<String, Integer> indexCell = new TableCell<>();
ReadOnlyObjectProperty<TableRow<String>> rowProperty = indexCell.tableRowProperty();
ObjectBinding<String> rowBinding = Bindings.createObjectBinding(() -> {
TableRow<String> row = rowProperty.get();
if (row != null) {
int rowIndex = row.getIndex();
if (rowIndex < row.getTableView().getItems().size()) {
return Integer.toString(rowIndex);
}
}
return null;
}, rowProperty);
indexCell.textProperty().bind(rowBinding);
return indexCell;
});
TableColumn<String, String> nameColumn = new TableColumn<>("name");
nameColumn.setCellValueFactory(f -> new ReadOnlyObjectWrapper<>(f.getValue()));
ObservableList<TableColumn<String, ?>> columns = table.getColumns();
columns.add(indexColumn);
columns.add(nameColumn);
Group root = new Group();
root.getChildren().add(table);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
stage.sizeToScene();
}
public static void main(String[] args) {
launch(args);
}
}
@BuiHoangTu
Copy link

BuiHoangTu commented Feb 2, 2023

I made a CallBack according to your code

public class IndexCallBack<S> implements Callback<TableColumn<S, Integer>, TableCell<S, Integer>> {
	@Override
	public TableCell<S, Integer> call(TableColumn<S, Integer> sIntegerTableColumn) {
		TableCell<S, Integer> indexCell = new TableCell<>();
		ReadOnlyObjectProperty<TableRow<S>> rowProperty = indexCell.tableRowProperty();
		ObjectBinding<Integer> rowBinding = Bindings.createObjectBinding(
				() -> {
					TableRow<S> row = rowProperty.get();
					if (row != null) {
						int rowIndex = row.getIndex();
						if (rowIndex < row.getTableView().getItems().size()) {
							return rowIndex;
						}
					}
					return null;
				},
				rowProperty
		);
		indexCell.textProperty().bind(new SimpleStringProperty(rowBinding.toString()));
		return indexCell;
	}
}

And I got ObjectBinding[invalid] for index column.

@dmolesUC
Copy link
Author

dmolesUC commented Feb 3, 2023

@BuiHoangTu I haven't looked at JavaFX in years (and haven't been doing much Java at all lately) but it looks like your SimpleStringProperty is calling toString() on the ObjectBinding itself. That's not going to get you the bound value, it's just going to get you the string representation of the binding object.

You'll notice that in my code it's not an ObjectBinding<Integer>, it's an ObjectBinding<String> (which could probably be a StringBinding, actually), and the int to String conversion happens inside the binding (see line 34).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment