绑定JavaFX TableView中所有单元格的样式属性

时间:2013-09-13 16:35:09

标签: javafx-2

我有一个JavaFX TableView,其中每一行都应该有一个条件样式。

样式取决于表行的源项是否存在于某个列表中。

这是我到目前为止所做的:

1)保存表行数据的数据类以及两个布尔属性(如果数据包含在列表X中,则为true)和应绑定到正确样式属性的字符串属性。

private class WebPageData {
    private WebPage page;

    private BooleanProperty isReferenced = new SimpleBooleanProperty(false);
    private BooleanProperty isReferencing = new SimpleBooleanProperty(false);

    private StringBinding style = new When(isReferenced).then("...").otherwise(...);
}

2)表选择更改时的更改侦听器会在表选择更改时相应地更新每个布尔属性

tblResultData.getSelectionModel().getSelectedIndices().addListener(new ListChangeListener<Integer>() {
        @Override
        public void onChanged(ListChangeListener.Change<? extends Integer> arg0) {
            if (arg0.getList().size() == 0) {
                selectedPage.set(null);
            } else {
                // for coloring only consider the first selected row
                // multi select must be doable for certain other features
                WebPage selectedWebPage = tblResultData.getItems().get(arg0.getList().get(0)).page;
                selectedPage.set(selectedWebPage);

                // tableModel.data holds a list of data for every table row
                for (WebPageData data : tableModel.data) {
                    boolean referenced = selectedWebPage.getReferencedWebPagesList().contains(data.page);
                    boolean referencing = selectedWebPage.getReferencingWebPagesList().contains(data.page);

                    data.isReferenced.set(referenced);
                    data.isReferencing.set(referencing);
                }
            }
        }
    });

现在我要做的是以某种方式将每个表格单元格的样式属性绑定到WebPageData的样式属性 - 以便更改侦听器更新两个布尔属性,因此更新了WebPageData的样式属性,因此表格单元格的样式发生了变化。

我尝试在创建阶段使用自定义TableCellFactory绑定样式,但当然这种方法失败,因为此时没有WebPageData实例。由于TableColumn类没有提供迭代所有单元格的机会(所以我可以在表实际获取其数据后绑定样式),我目前看到的唯一选项是保持对每个创建的表格单元格的引用。我不认为这个解决方案是好的做法。

那么还有其他选项来绑定单元格样式吗?如果我不绑定它们,我必须在每次表格选择改变时手动设置样式 - 这使我再次进入“我无法迭代细胞”问题。

1 个答案:

答案 0 :(得分:1)

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.scene.control.TreeTableRow;

public class HighlightBoundTreeTableRow extends TreeTableRow<Thing> {

    private static final String CHOSEN_STYLE_CLASS = "chosenStyle";

    private final ObjectProperty<Boolean> chosen = new SimpleObjectProperty<>();

    private final ChangeListener propertyChangeListener = (obs, ov, nv) -> updateHighlight();

    @Override
    protected void updateItem(Thing item, boolean empty) {
        super.updateItem(item, empty);

        //cleanup
        getStyleClass().remove(CHOSEN_STYLE_CLASS);
        chosen.unbind(); // unbinding something that is not bound has no effect
        chosen.removeListener(propertyChangeListener); // also ok to remove a listener that was never there

        if (empty) {
            return;
        }

        chosen.bind(item.chosenProperty()); //bind will also set the intial value
        chosen.addListener(propertyChangeListener);

        updateHighlight();
    }

    private void updateHighlight() {
        if (chosen.get()) {
            getStyleClass().add(CHOSEN_STYLE_CLASS);
        } else {
            getStyleClass().remove(CHOSEN_STYLE_CLASS);
        }
    }
}

我知道这是永远被问到的,但也许它会帮助别人。

我有一个类似的问题我想解决。我知道你正在使用一个TableCell,这涉及一个TreeTableRow,但我相信这个概念是相同的:你想要更改数据对象中的一个字段,并让该更改更新该对象在表中显示的任何位置的样式。

所以我扩展了TreeTableRow并为该类提供了自己的属性字段来保持。每次更新该行时,我取消绑定该属性并将其重新绑定到我想要侦听的字段。 (我对侦听器也这样做。)因为每次调用updateItem()时都可能获得我的数据对象的不同实例。

“selectedStyle”只是我样式表中的一个类,用于更改背景颜色。使用类而不是调用setStyle()可以更容易地删除样式。