Javafx 如何强制TableRow重新绘制

Javafx 如何强制TableRow重新绘制,javafx,Javafx,如何强制TableRow重新绘制 设想以下场景:tableView每180毫秒更新一次,但是接收TableRow样式信息的单元格不可见,并且每次升级TableRow时都需要重新绘制。当我使用refresh()方法时,它看起来不太好,特别是当鼠标定位在TableView上时,它会闪烁,在这种情况下会消耗cpu myTableView.setRowFactory( new Callback<TableView, TableRow<Line>>() { @Ov

如何强制TableRow重新绘制

设想以下场景:tableView每180毫秒更新一次,但是接收TableRow样式信息的单元格不可见,并且每次升级TableRow时都需要重新绘制。当我使用refresh()方法时,它看起来不太好,特别是当鼠标定位在TableView上时,它会闪烁,在这种情况下会消耗cpu

myTableView.setRowFactory( new Callback<TableView, TableRow<Line>>() {

        @Override
        public TableRow call(final TableView p) {
            return new TableRow<Line>() {

                @Override
                public void updateItem(Line item, boolean empty) {
                    super.updateItem(item, empty);
                    if(item != null) {
                        if(item.statusProperty().getValue().equals("BORDER")) {
                           setStyle("-fx-border-color:green;-fx-border-width:2;-fx-opacity:1;"); 

                        }   
                    }    
                }
            };

        }
    });    
myTableView.setRowFactory(新回调(){
@凌驾
公共TableRow调用(最终TableView p){
返回新的TableRow(){
@凌驾
public void updateItem(行项目,布尔值为空){
super.updateItem(项,空);
如果(项!=null){
if(item.statusProperty().getValue().equals(“边框”)){
设置样式(“-fx边框颜色:绿色;-fx边框宽度:2;-fx不透明度:1;”);
}   
}    
}
};
}
});    

由于样式取决于可观察的
行的
statusProperty()
,因此可以使用绑定:

@Override
public void updateItem(Line item, boolean empty) {
    super.updateItem(item, empty);
    if(item != null) {
        styleProperty().bind(Bindings
            .when(item.statusProperty().isEqualTo("BORDER"))
            .then("-fx-border-color:green;-fx-border-width:2;-fx-opacity:1;")
            .otherwise("")); 
    } else {
        styleProperty().unbind();
        setStyle("");
    } 
}
另一种创建绑定的方法是

@Override
public void updateItem(Line item, boolean empty) {
    super.updateItem(item, empty);
    if(item != null) {
        styleProperty().bind(Bindings.createStringBinding(() -> {
            if ("BORDER".equals(item.getStyle())) {
                return "-fx-border-color:green;-fx-border-width:2;-fx-opacity:1;" ;
            } else {
                return "" ;
            }
        }, item.statusProperty()); 
    } else {
        styleProperty().unbind();
        setStyle("");
    } 
}
这样,表行将观察当前项的status属性,并在该属性更改时自动更新样式

当然,如果您真的想让代码更干净,您应该将样式移动到外部CSS文件中。您可以创建一个CSS
伪类(或多个),您可以在行上设置和取消设置该类:

final PseudoClass borderPC = PseudoClass.getPseudoClass("border");
myTableView.setRowFactory(p -> {
    TableRow<Line> row = new TableRow<>();
    ChangeListener<String> statusListener = (obs, oldStatus, newStatus) -> 
        row.pseudoClassStateChanged(borderPC, "BORDER".equals(newStatus)) ;

    row.itemProperty().addListener((obs, oldLine, newLine) -> {
        if (oldLine != null) {
            oldLine.statusProperty().removeListener(statusListener);
        }
        if (newLine == null) {
            row.pseudoClassStateChanged(borderPC, false);
        } else {
            newLine.statusProperty().addListener(statusListener);
            row.pseudoClassStateChanged(borderPC, "BORDER".equals(newLine.getStatus()));
        }
    };

    return row ;
});

同样,使用这种方法,您可以轻松地向CSS添加更多的psuedo类、更多的规则以及其他测试和伪类更新。

这个解决方案非常有趣。但是…,如果我有很多示例选择,如果“Border”然后“-fx Border color:绿色;-fx Border width:2;-fx opacity:1;“如果“OpacityOff”然后“-fx opacity:0.3”;其他…@Tretonis您可以在
调用中包装更多
绑定。when().then().other()
,但这很快就会变得难看。我用另一种更容易扩展到更复杂逻辑的方法编辑了答案。非常感谢您分享您的时间和知识。伪类解决方案中似乎缺少括号。我无法添加它,因为编辑至少需要6个字符。。。