Last active
September 11, 2017 23:39
-
-
Save james-d/85233c1fb6343c5f7df69257322ff8f7 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.HashMap; | |
import java.util.Map; | |
import java.util.Random; | |
import java.util.function.Function; | |
import javafx.animation.KeyFrame; | |
import javafx.animation.KeyValue; | |
import javafx.animation.Timeline; | |
import javafx.application.Application; | |
import javafx.beans.property.IntegerProperty; | |
import javafx.beans.property.SimpleIntegerProperty; | |
import javafx.beans.property.SimpleStringProperty; | |
import javafx.beans.property.StringProperty; | |
import javafx.beans.value.ObservableValue; | |
import javafx.geometry.Bounds; | |
import javafx.geometry.Insets; | |
import javafx.geometry.Pos; | |
import javafx.scene.Scene; | |
import javafx.scene.control.Button; | |
import javafx.scene.control.Label; | |
import javafx.scene.control.RadioButton; | |
import javafx.scene.control.TableCell; | |
import javafx.scene.control.TableColumn; | |
import javafx.scene.control.TableView; | |
import javafx.scene.control.TextField; | |
import javafx.scene.control.TextFormatter; | |
import javafx.scene.control.TextFormatter.Change; | |
import javafx.scene.control.ToggleGroup; | |
import javafx.scene.layout.BorderPane; | |
import javafx.scene.layout.GridPane; | |
import javafx.scene.layout.Pane; | |
import javafx.scene.paint.Color; | |
import javafx.scene.shape.Circle; | |
import javafx.stage.Stage; | |
import javafx.util.Duration; | |
import javafx.util.StringConverter; | |
public class KeepTrackOfTableCells extends Application { | |
private Map<TableColumn<Item, ?>, Map<Number, TableCell<Item, ?>>> cells ; | |
@Override | |
public void start(Stage primaryStage) { | |
cells = new HashMap<>(); | |
TableView<Item> table = new TableView<>(); | |
table.getColumns().add(column("Item", Item::nameProperty)); | |
table.getColumns().add(column("Value", Item::valueProperty)); | |
Random rng = new Random(); | |
for (int i = 1 ; i <= 100 ; i++) { | |
table.getItems().add(new Item("Item "+ i, rng.nextInt(500))); | |
} | |
TextField indexField = new TextField(); | |
TextFormatter<Integer> formatter = new TextFormatter<>( | |
new StringConverter<Integer>() { | |
@Override | |
public String toString(Integer object) { | |
return object.toString(); | |
} | |
@Override | |
public Integer fromString(String string) { | |
if (string.isEmpty()) return 0 ; | |
return Integer.valueOf(string); | |
} | |
}, | |
0, | |
(Change c) -> c.getText().matches("\\d*") ? c : null | |
) ; | |
indexField.setTextFormatter(formatter); | |
RadioButton name = new RadioButton("Item column"); | |
RadioButton value = new RadioButton("Value column"); | |
ToggleGroup tg = new ToggleGroup(); | |
tg.getToggles().addAll(name, value); | |
name.setSelected(true); | |
Button search = new Button("Find"); | |
GridPane controls = new GridPane(); | |
controls.setVgap(5); | |
controls.setHgap(5); | |
controls.add(new Label("Row (1-based):"), 0, 0); | |
controls.add(indexField, 1, 0); | |
controls.add(name, 0, 2, 2, 1); | |
controls.add(value, 0, 3, 2, 1); | |
controls.add(search, 0, 4); | |
Pane root = new Pane(); | |
BorderPane ui = new BorderPane(); | |
BorderPane.setAlignment(controls, Pos.CENTER); | |
BorderPane.setMargin(controls, new Insets(5)); | |
BorderPane.setMargin(table, new Insets(5)); | |
ui.setTop(controls); | |
ui.setCenter(table); | |
root.getChildren().add(ui); | |
search.setOnAction(e -> { | |
TableColumn<Item,?> col = name.isSelected() ? table.getColumns().get(0) : table.getColumns().get(1); | |
int index = formatter.getValue() - 1; | |
TableCell<Item,?> cell = cells.get(col).get(index); | |
if (cell != null) { | |
Bounds bounds = root.sceneToLocal(cell.localToScene(cell.getBoundsInLocal())); | |
double x = (bounds.getMinX() + bounds.getMaxX()) / 2 ; | |
double y = (bounds.getMinY() + bounds.getMaxY()) / 2 ; | |
Circle c = new Circle(0, 0, 5, Color.BLUE); | |
root.getChildren().add(c); | |
new Timeline( | |
new KeyFrame(Duration.seconds(1), | |
new KeyValue(c.centerXProperty(), x), | |
new KeyValue(c.centerYProperty(), y)), | |
new KeyFrame(Duration.seconds(2), evt -> root.getChildren().remove(c)) | |
).play(); | |
} | |
}); | |
Scene scene = new Scene(root); | |
primaryStage.setScene(scene); | |
primaryStage.show(); | |
} | |
private <T> TableColumn<Item,T> column(String title, Function<Item, ObservableValue<T>> property) { | |
TableColumn<Item,T> col = new TableColumn<>(title); | |
col.setCellValueFactory(cellData -> property.apply(cellData.getValue())); | |
cells.put(col, new HashMap<Number, TableCell<Item, ?>>()); | |
col.setCellFactory(tc -> { | |
TableCell<Item, T> cell = new TableCell<Item, T>() { | |
@Override | |
protected void updateItem(T item, boolean empty) { | |
super.updateItem(item, empty); | |
if (empty) { | |
setText(null); | |
} else { | |
setText(item.toString()) ; | |
} | |
} | |
}; | |
cell.indexProperty().addListener((obs, oldIndex, newIndex) -> { | |
if (oldIndex != null && oldIndex.intValue() != -1 ) { | |
cells.get(col).remove(oldIndex); | |
} | |
if (newIndex != null && newIndex.intValue() != -1) { | |
cells.get(col).put(newIndex, cell); | |
} | |
}); | |
return cell ; | |
}); | |
col.setSortable(false); | |
return col ; | |
} | |
public static class Item { | |
private final StringProperty name = new SimpleStringProperty(); | |
private final IntegerProperty value = new SimpleIntegerProperty(); | |
public Item(String name, int value) { | |
setName(name); | |
setValue(value); | |
} | |
public StringProperty nameProperty() { | |
return name ; | |
} | |
public final String getName() { | |
return nameProperty().get(); | |
} | |
public final void setName(String name) { | |
nameProperty().set(name); | |
} | |
public IntegerProperty valueProperty() { | |
return value ; | |
} | |
public final int getValue() { | |
return valueProperty().get(); | |
} | |
public final void setValue(int value) { | |
valueProperty().set(value); | |
} | |
} | |
public static void main(String[] args) { | |
launch(args); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment