JavaFX TableView - 同一行中新Cell的新值 [英] JavaFX TableView - New Values in new Cell in same Row

查看:147
本文介绍了JavaFX TableView - 同一行中新Cell的新值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了以下问题:

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

I styled a TableViews Cells into Rectangles. Now I want to add Objects with an X and Y Coordinate in it (obj.getAblaufX() and obj.getAblaufY()). How can I add them correctly in 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);
}

结果:

但是:

对象SP1有X = 0和Y = 0

对象SP2有X = 1而Y = 0

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

So, how to fix this Problem?

推荐答案

使用事件作为项目类型,你通过在每行显示多个事件来实现 TableView 。使用 Integer 作为项目类型,并将值存储在 ObservableMap< TablePos,Event> 其中 TablePos 是一个包含 x y 坐标的类:

By using Event as item type, you pervent the TableView from displaying more than one Event per row. Use Integer as item type instead and store the values in a ObservableMap<TablePos, Event> where TablePos is a class containing the x and y coordinates:

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 添加一个监听器,动态添加/删除行/列。

Note that this requires you to know the number of rows/columns at the initialisation (I used 10 for both for simplicity). If this is not the case, you could add a listener to the ObservableMap that dynamically adds/removes rows / columns.

这篇关于JavaFX TableView - 同一行中新Cell的新值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆