2017-06-01 139 views
1

如何強制TableRow重繪?如何強制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;"); 

         } 
        }  
       } 
      }; 

     } 
    });  

回答

2

由於風格依賴於Line,這是觀察到的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(""); 
    } 
} 

這樣的錶行就會觀察當前項目的狀態屬性,並自動更新樣式如果該財產發生變化。

如果您確實想讓代碼更清潔,當然,您應該將樣式移動到外部CSS文件。您可以創建在該行一個CSS PseudoClass(或多個),你可以設置和取消:

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文件,做

.table-row-cell:border { 
    -fx-border-color:green; 
    -fx-border-width:2; 
    -fx-opacity:1; 
} 

同樣,你可以輕鬆地添加更多僞代碼,CSS的更多規則,以及使用此方法的其他測試和僞類更新。

+0

這個解決方案非常有趣。 但是,如果我有很多樣本選擇,我將如何看待 如果「邊框」,那麼「-fx-border-color:green; -fx-border-width:2; -fx-opacity:1;」 如果「OpacityOff」則是「-fx-opacity:0.3;」 其他...... – Tretonis

+0

@Tretonis你可以在''otherwise(...)'調用內包裝更多的'Bindings.when()。then()。otherwise()',但這會很快變得難看。我用另一種更容易擴展到更復雜邏輯的方法編輯答案。 –

+0

非常感謝您分享您的時間和知識。 – Tretonis