JavaFX TableView - 同一行中新单元格中的新值

时间:2016-06-09 06:19:50

标签: java javafx tableview coordinates

我遇到了以下问题:

我将TableViews单元格设置为矩形。现在我想添加带有X和Y坐标的对象(obj.getAblaufX()obj.getAblaufY())。 如何在JavaFX TableView中正确添加它们?

我当前的代码:

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);
}

结果:

enter image description here

可是:

对象SP1的X = 0且Y = 0

对象SP2的X = 1且Y = 0

那么,如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

通过使用app:showAsAction="never" 作为项类型,您可以确保Event每行显示多个TableView。请改为使用Event作为项目类型,并将值存储在Integer ObservableMap<TablePos, Event>,其中TablePos是包含xy坐标的类:

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();
}

请注意,这需要您知道初始化时的行数/列数(为简单起见,我使用了10行)。如果不是这种情况,您可以向动态添加/删除行/列的ObservableMap添加一个侦听器。