auto numbered table rows (javafx)


Question

My question is how to make a new Table in JavaFX with in the first column the index of the tableRow.

So i've created a class: NrCellFactory.

public class NrCellFactory<S, String> extends TableCellFactory<S,String> {

private class NrCell<S,String> extends TableCell<S,String>{

    public NrCell(){
        setText(this.getTableRow().getIndex()+"");
    }



}

@Override
protected TableCell<S, String> createTableCell(TableColumn<S, String> column) {
    return new NrCell();
}

}

and then i set my column where the numbers should be displayed:

 nrCol.setCellFactory(new NrCellFactory<Person,String>());

when I load the project, the nrCol has no data...

Can anyone solve the problem?

Thanks

1
8
5/5/2013 1:11:01 PM

Sample Solution

Here's a solution using a cell factory:

TableColumn numberCol = new TableColumn("#");
numberCol.setCellValueFactory(new Callback<CellDataFeatures<Person, Person>, ObservableValue<Person>>() {
  @Override public ObservableValue<Person> call(CellDataFeatures<Person, Person> p) {
    return new ReadOnlyObjectWrapper(p.getValue());
  }
});

numberCol.setCellFactory(new Callback<TableColumn<Person, Person>, TableCell<Person, Person>>() {
  @Override public TableCell<Person, Person> call(TableColumn<Person, Person> param) {
    return new TableCell<Person, Person>() {
      @Override protected void updateItem(Person item, boolean empty) {
        super.updateItem(item, empty);

        if (this.getTableRow() != null && item != null) {
          setText(this.getTableRow().getIndex()+"");
        } else {
          setText("");
        }
      }
    };
  }
});
numberCol.setSortable(false);

Simple Alternate Solution

And a simpler sample using a cell value factory and no cell factory for the normal case where all of the items in the backing data list for the table are unique and their index can be looked up via table.getItems().indexOf(p.getValue()):

TableColumn numberCol = new TableColumn("#");
numberCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
  @Override public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
    return new ReadOnlyObjectWrapper(table.getItems().indexOf(p.getValue()) + "");
  }
});   
numberCol.setSortable(false);

Why your attempt to do this failed

I couldn't say exactly why your attempt to do this failed as I don't think there is enough code in your question to accurately diagnose the failure. My guess is that you didn't provide a cell value factory for the row and also setting the text in the cell's constructor rather than an updateItem call caused it not to work.

Executable Sample

Here is an executable sample:

tableviewnumberedrows

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;

public class NumberedTableViewSample extends Application {

    private TableView<Person> table = new TableView<Person>();
    private final ObservableList<Person> data =
        FXCollections.observableArrayList(
            new Person("Jacob", "Smith", "jacob.smith@example.com"),
            new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
            new Person("Ethan", "Williams", "ethan.williams@example.com"),
            new Person("Emma", "Jones", "emma.jones@example.com"),
            new Person("Michael", "Brown", "michael.brown@example.com")
        );

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(470);
        stage.setHeight(500);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        table.setEditable(true);

        TableColumn numberCol = new TableColumn("#");
        numberCol.setMinWidth(20);
        numberCol.setCellValueFactory(new Callback<CellDataFeatures<Person, Person>, ObservableValue<Person>>() {
            @Override public ObservableValue<Person> call(CellDataFeatures<Person, Person> p) {
                return new ReadOnlyObjectWrapper(p.getValue());
            }
        });

        numberCol.setCellFactory(new Callback<TableColumn<Person, Person>, TableCell<Person, Person>>() {
            @Override public TableCell<Person, Person> call(TableColumn<Person, Person> param) {
                return new TableCell<Person, Person>() {
                    @Override protected void updateItem(Person item, boolean empty) {
                        super.updateItem(item, empty);

                        if (this.getTableRow() != null && item != null) {
                            setText(this.getTableRow().getIndex()+"");
                        } else {
                            setText("");
                        }
                    }
                };
            }
        });
        numberCol.setSortable(false);

        TableColumn firstNameCol = new TableColumn("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("firstName"));

        TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("lastName"));

        TableColumn emailCol = new TableColumn("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("email"));

        table.setItems(data);
        table.getColumns().addAll(numberCol, firstNameCol, lastNameCol, emailCol);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);
        stage.setScene(scene);
        stage.show();
    }

    public static class Person {

        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;

        private Person(String fName, String lName, String email) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String fName) {
            lastName.set(fName);
        }

        public String getEmail() {
            return email.get();
        }

        public void setEmail(String fName) {
            email.set(fName);
        }
    }
} 
20
5/6/2013 9:11:45 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon