Last active
June 1, 2018 15:13
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In Java 8, the mess that is creating and setting the cellFactory reduces just to
sortCombo.setCellFactory(listView -> createListCell());