3

我有一个 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 类不提供迭代所有单元格的机会(因此我可以在表格实际获取其数据后绑定样式),我目前看到的唯一选择是保留对每个创建的表格单元格的引用。我不认为这个解决方案是好的做法。

那么还有其他选项可以绑定单元格样式吗?如果我不绑定它们,我必须在每次表格选择更改时手动设置样式——这让我再次陷入“我无法遍历单元格”的问题。

4

1 回答 1

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() 时,它可能会获取我的数据对象的不同实例。

“chosenStyle”只是我样式表中的一个类,它改变了背景颜色。使用类而不是调用 setStyle() 可以更轻松地删除样式。

于 2017-12-18T17:45:22.503 回答