Wenn Sie Event
als Elementtyp verwenden, können Sie die TableView
von mehr als einer Event
pro Zeile anzeigen. Verwenden Sie Integer
als Element eingeben statt und speichern die Werte in einem ObservableMap<TablePos, Event>
wo TablePos
eine Klasse enthält, ist die x
und y
Koordinaten:
public final class TablePos {
private final int x;
private final int y;
public TablePos(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
int hash = 7;
hash = 17 * hash + this.x;
hash = 17 * hash + this.y;
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof TablePos)) {
return false;
}
final TablePos other = (TablePos) obj;
return (this.x == other.x && this.y == other.y);
}
}
public class Event {
private final StringProperty name;
private final IntegerProperty x;
private final IntegerProperty y;
public Event(String name, int x, int y) {
// set beans for properties here to make this instance accessible to listeners
this.y = new SimpleIntegerProperty(this, "y", y);
this.x = new SimpleIntegerProperty(this, "x", x);
this.name = new SimpleStringProperty(this, "name", name);
}
public final String getName() {
return this.name.get();
}
public final void setName(String value) {
this.name.set(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final int getX() {
return this.x.get();
}
public final void setX(int value) {
this.x.set(value);
}
public final IntegerProperty xProperty() {
return this.x;
}
public final int getY() {
return this.y.get();
}
public final void setY(int value) {
this.y.set(value);
}
public final IntegerProperty yProperty() {
return this.y;
}
}
private static void put(Map<TablePos, Event> map, Event evt) {
map.put(new TablePos(evt.getX(), evt.getY()), evt);
}
@Override
public void start(Stage primaryStage) {
ObservableMap<TablePos, Event> contents = FXCollections.observableHashMap();
TableView<Integer> tableView = new TableView<>(FXCollections.observableArrayList());
TableColumn columnGroup = new TableColumn("Heutige Termine");
ChangeListener<Number> xChangeListener = (observable, oldValue, newValue) -> {
Event evt = (Event) ((Property) observable).getBean();
TablePos oldPos = new TablePos(oldValue.intValue(), evt.getY());
TablePos newPos = new TablePos(newValue.intValue(), evt.getY());
contents.remove(oldPos);
contents.put(newPos, evt);
};
ChangeListener<Number> yChangeListener = (observable, oldValue, newValue) -> {
Event evt = (Event) ((Property) observable).getBean();
TablePos oldPos = new TablePos(evt.getX(), oldValue.intValue());
TablePos newPos = new TablePos(evt.getX(), newValue.intValue());
contents.remove(oldPos);
contents.put(newPos, evt);
};
contents.addListener((MapChangeListener.Change<? extends TablePos, ? extends Event> change) -> {
if (change.wasRemoved()) {
Event evt = change.getValueRemoved();
evt.xProperty().removeListener(xChangeListener);
evt.yProperty().removeListener(yChangeListener);
}
if (change.wasAdded()) {
Event evt = change.getValueAdded();
evt.xProperty().addListener(xChangeListener);
evt.yProperty().addListener(yChangeListener);
}
});
// items denote the y coordinate
for (int i = 0; i < 10; i++) {
tableView.getItems().add(i);
}
// one column per x coordiante
for (int i = 0; i < 10; i++) {
final int index = i;
TableColumn<Integer, String> column = new TableColumn<>();
// take value from Map using x (index) and y (item value)
column.setCellValueFactory(cd
-> Bindings.selectString(
Bindings.valueAt(contents, new TablePos(index, cd.getValue())), "name"));
columnGroup.getColumns().add(column);
}
tableView.getColumns().add(columnGroup);
Event opTarget = new Event("Something", 2, 9);
put(contents, new Event("SP1", 0, 0));
put(contents, new Event("SP2", 1, 0));
put(contents, opTarget);
Button move = new Button("move");
move.setOnAction(evt -> opTarget.setX(9 - opTarget.getX()));
Button rename = new Button("rename");
rename.setOnAction(evt -> opTarget.setName(opTarget.getName().equals("42") ? "Answer" : "42"));
Scene scene = new Scene(new VBox(10, tableView, move, rename));
primaryStage.setScene(scene);
primaryStage.show();
}
Beachten Sie, dass diese Sie das wissen müssen Anzahl der Zeilen/Spalten bei der Initialisierung (Ich habe 10 für beide zur Vereinfachung verwendet). Wenn dies nicht der Fall ist, können Sie dem ObservableMap
einen Listener hinzufügen, der Zeilen/Spalten dynamisch hinzufügt/entfernt.
vielen Dank! –
und ja, Event kann geändert werden. Ich habe Int in IntegerProperty geändert. Aber wie fügt man den Listener hinzu? –
@ Mr.0x50: Beispiel geändert, um eine benutzerdefinierte "Event" -Klasse zu verwenden, die Positionen bei Eigenschaftsänderungen aktualisiert. – fabian