在订购TableView时,TableRow样式类不会粘在行上

时间:2018-05-20 11:11:15

标签: java javafx

我想根据行项中的布尔值将样式类添加/删除到表行。

使用以下代码添加和删除类可以按预期工作。但是,当我单击列标题以重新排序表时,样式会粘贴到行ID而不是行项。意思是如果在订购之前第一行被设置样式,在订购之后样式仍然在第一行而不是新位置的行。

setRowFactory(table -> {
    TableRow<PowerPlantPM> row = new TableRow<>() {
        @Override
        protected void updateItem(PowerPlantPM pp, boolean empty) {
            super.updateItem(pp, empty);
            if (!empty && pp != null) {
                pp.savedProperty().addListener((observable, oldValue, newValue) -> {
                    if (newValue) {
                        getStyleClass().remove("unsaved");
                    } else {
                        getStyleClass().add("unsaved");
                    }
                });
                // the following binding works (including ordering), but is not what I want because of the ":selected" pseudo class
                // styleProperty().bind(Bindings.when(pp.savedProperty()).then("").otherwise("-fx-background-color: #f2dede"));
            }
        }
    };
    return row;
});

我希望很清楚我想要实现的目标。重新排序时,如何让样式粘在行项上?

2 个答案:

答案 0 :(得分:1)

尽可能重用TableRow,在updateItem中,您需要查询相应的属性,而不是向其添加侦听器。只有在属性发生变化时才会触发监听器,但TableRow可能会要求重新绘制其他位置或不同的项目。

protected void updateItem(PowerPlantPM pp, boolean empty) {
        super.updateItem(pp, empty);
        if (!empty && pp != null) {
            if (!pp.isSaved()) {
                 getStyleClass().add("unsaved");
            } else {
                 getStyleClass().remove("unsaved");
            }
            .....
        }
 }

使用

创建的属性创建ObservableList
 ObservableListFX<PowerPlantPM> powerplants = 
   Collections.observableArrayList(pp -> new Observable[] { pp.savedProperty() }); 

此列表将报告您在Observable[]

中返回的属性的项目更改

答案 1 :(得分:1)

您永远不会从旧项目中取消注册侦听器。此外,不会为侦听器调用属性的初始值。即使它是,您的代码也可能导致相同的样式类被多次添加到节点。此外,细胞可能变空。在这种情况下你也需要删除样式类。

为避免多次添加相同的样式类,请使用伪类:

final PseudoClass unsaved = PseudoClass.getPseudoClass("unsaved");

setRowFactory(table -> {
    TableRow<PowerPlantPM> row = new TableRow<>() {
        private final ChangeListener<Boolean> listener = (observable, oldValue, newValue) -> {
            pseudoClassStateChanged(unsaved, !newValue);
        };

        @Override
        protected void updateItem(PowerPlantPM pp, boolean empty) {
            PowerPlantPM oldItem = getItem();
            if (oldItem != null) {
                // remove old listener
                oldItem.savedProperty().removeListener(listener);
            }

            super.updateItem(pp, empty);
            if (empty || pp == null) {
                // remove pseudoclass from empty cell
                pseudoClassStateChanged(unsaved, false);
            } else {
                // add new listener & handle initial value
                pp.savedProperty().addListener(listener);
                pseudoClassStateChanged(unsaved, pp.isSaved());
            }
        }
    };
    return row;
});

(当然,您需要调整CSS选择器以使用:unsaved而不是.unsaved。)

相关问题