Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
You can’t perform that action at this time.