Skip to content

Instantly share code, notes, and snippets.

@james-d
Last active June 1, 2018 15:13
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save james-d/7294358 to your computer and use it in GitHub Desktop.
Save james-d/7294358 to your computer and use it in GitHub Desktop.
TableView that sorts either by clicking on the column headers or by selecting a column from a combo box.
import java.util.Arrays;
import java.util.Collections;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn.SortType;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ComboBoxSortableTable extends Application {
@Override
public void start(Stage primaryStage) {
final BorderPane root = new BorderPane();
final TableView<Person> table = new TableView<Person>();
table.setItems(createData());
final TableColumn<Person, String> firstNameColumn = new TableColumn<>("First Name");
final TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
lastNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
table.getColumns().addAll(Arrays.asList(firstNameColumn, lastNameColumn));
root.setCenter(table);
final ComboBox<TableColumn<Person, ?>> sortCombo = new ComboBox<>(table.getColumns());
// Generics hell... much nicer if you can use Java8 lambda expressions
final Callback<ListView<TableColumn<Person, ?>>, ListCell<TableColumn<Person, ?>>> cellFactory = new Callback<ListView<TableColumn<Person, ?>>, ListCell<TableColumn<Person, ?>>>(){
@Override
public ListCell<TableColumn<Person, ?>> call(ListView<TableColumn<Person, ?>> listView) {
return createListCell();
}
};
sortCombo.setCellFactory(cellFactory);
sortCombo.setButtonCell(createListCell());
sortCombo.valueProperty().addListener(new ChangeListener<TableColumn<Person, ?>>() {
@Override
public void changed(ObservableValue<? extends TableColumn<Person, ?>> obs,
TableColumn<Person, ?> oldCol, TableColumn<Person, ?> newCol) {
if (newCol != null) {
table.getSortOrder().setAll(Collections.singletonList(newCol));
newCol.setSortType(SortType.ASCENDING);
} else {
table.getSortOrder().clear();
}
}
});
table.getSortOrder().addListener(new ListChangeListener<TableColumn<Person, ?>>() {
@Override
public void onChanged(Change<? extends TableColumn<Person, ?>> change) {
while (change.next()) {
if (change.wasAdded()) {
sortCombo.setValue(table.getSortOrder().get(0));
}
}
}
});
root.setTop(sortCombo);
final Scene scene = new Scene(root, 400, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private ListCell<TableColumn<Person, ?>> createListCell() {
final ListCell<TableColumn<Person, ?>> cell = new ListCell<>();
cell.itemProperty().addListener(new ChangeListener<TableColumn<Person, ?>>() {
@Override
public void changed(
ObservableValue<? extends TableColumn<Person, ?>> obs,
TableColumn<Person, ?> oldColumn, TableColumn<Person, ?> newColumn) {
if (newColumn==null) {
cell.setText(null);
} else {
cell.setText(newColumn.getText());
}
}
});
return cell ;
}
public static void main(String[] args) {
launch(args);
}
private ObservableList<Person> createData() {
return FXCollections.observableArrayList(
new Person("Hugo", "Lloris"),
new Person("Danny", "Rose"),
new Person("Jan", "Vertonghen"),
new Person("Michael", "Dawson"),
new Person("Kyle", "Walker"),
new Person("Sandro", "Raniere"),
new Person("Paulinho", "Maciel"),
new Person("Gylfi", "Sigurdsson"),
new Person("Andros", "Townsend"),
new Person("Aaron", "Lennon"),
new Person("Roberto", "Soldado"));
}
public static class Person {
private final StringProperty firstName;
private final StringProperty lastName;
Person(String firstName, String lastName) {
this.firstName = new SimpleStringProperty(this, "firstName",
firstName);
this.lastName = new SimpleStringProperty(this, "lastName", lastName);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public StringProperty firstNameProperty() {
return firstName;
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public StringProperty lastNameProperty() {
return lastName;
}
@Override
public String toString() {
return firstName.get() + " " + lastName.get();
}
}
}
@james-d
Copy link
Author

james-d commented Nov 3, 2013

In Java 8, the mess that is creating and setting the cellFactory reduces just to
sortCombo.setCellFactory(listView -> createListCell());

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