2016-06-09 3 views
1

Ich habe folgendes Problem:JavaFX TableView - Neue Werte in der neuen Zelle in derselben Zeile

Ich formatierte ein TableViews Zellen in Rechtecke. Jetzt möchte ich Objekte mit einer X- und Y-Koordinate hinzufügen (obj.getAblaufX() und obj.getAblaufY()). Wie kann ich sie in JavaFX TableView korrekt hinzufügen?

Mein aktueller Code:

ObservableList<Event> eventList = loadEvents(); 
TableView<Event> tableView = new TableView<Event>(); 
tableView.getSelectionModel().setCellSelectionEnabled(true); 
tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); 
tableView.setItems(eventList); 

for(int i = 0; i < 10; i++) { 
     TableColumn<Event, String> tmpCol = new TableColumn<>(); 
     tmpCol.setId(Integer.toString(i)); 
     tmpCol.setMaxWidth(40); 
     tmpCol.setCellValueFactory(cellData -> new ObservableValue<String>() { 
      @Override 
      public void addListener(InvalidationListener listener) { 
       // TODO Auto-generated method stub 
      } 
      @Override 
      public void removeListener(InvalidationListener listener) { 
       // TODO Auto-generated method stub 
      } 
      @Override 
      public void addListener(ChangeListener<? super String> listener) { 
       // TODO Auto-generated method stub 
      } 
      @Override 
      public void removeListener(ChangeListener<? super String> listener) { 
       // TODO Auto-generated method stub 
      } 
      @Override 
      public String getValue() { 
       if(Integer.parseInt(tmpCol.getId()) == cellData.getValue().getAblaufX()) { 
        return cellData.getValue().getAbteilung(); 
       } else { 
        return ""; 
       } 
      } 
     }); 

     tableView.getColumns().add(tmpCol); 
} 

Ergebnis:

enter image description here

Aber:

Objekt SP1 hat X = 0 und Y = 0

Objekt SP2 hat X = 1 und Y = 0

Also, wie Sie dieses Problem beheben?

Antwort

1

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.

+0

vielen Dank! –

+0

und ja, Event kann geändert werden. Ich habe Int in IntegerProperty geändert. Aber wie fügt man den Listener hinzu? –

+0

@ Mr.0x50: Beispiel geändert, um eine benutzerdefinierte "Event" -Klasse zu verwenden, die Positionen bei Eigenschaftsänderungen aktualisiert. – fabian

Verwandte Themen