2017-08-21 96 views
0

有一段時間我一直在試圖讓我的tableview的工作作爲一種電子表格是由後臺線程更新,當細胞得到更新,它幾秒鐘higlights(改變風格),然後返回到原來的風格。 我已經知道了,我不能直接存儲和表格單元格設置樣式,我需要某種形式的支持類的,這將保留該數據。但是,「重用」單元格的tableview(對不同的數據使用相同的單元格)行爲真的很奇怪。當所有的細胞適合在屏幕上它完美的作品對我來說,但一旦我把周圍的100個細胞,並將其變爲滾動它開始是越野車,有時樣式(或設置好的圖形)消失,出現滾動之後,如果停用來看一些頂尖的細胞,滾動後的一些其他單元也被禁用,等等。有沒有什麼正確的方法來做到這一點?什麼是正確的方式來使用tableview?

我需要的基本上是

Background data thread ---updates--> tableview 
Another thread --after few seconds removes style--> tableview 

,因爲我有現在,我有保存數據,風格和參考表格單元格模型類,它應該是(i禁用訂貨,所以它應該是確定)和後臺線程更新模型類中的數據,並且該模型類會在引用的單元格上更改樣式,並在「樣式移除器」線程中註冊自己,同時刪除樣式。

我認爲發佈我的實際代碼不會有用,因爲一旦我發現單元格正在被重用,我的代碼變得太複雜了,有點難以理解,所以我想完全重做它的正確方式。

Peformance是不是對我來說很重要,並且不會有超過100個細胞,但這種突出並具有按鈕的tableview必須工作得很好。

這是我的應用程序看起來像現在 - 爲的是什麼,我需要的想法。 enter image description here

編輯:這裏是鏈接到我的another question與此相關。

+1

沒有檢查代碼在您的其他問題,只是要注意:使用線程時,請確保到視覺效果的所有更新發生在FXApplication線程 – kleopatra

+0

我使用Platform.runLater進行每個可視化更新。另一個問題中的代碼已經不再那麼實際了,但我在那裏寫的答案與我現在使用的相同。我想在這裏鏈接另一個問題。 –

+0

我會模擬數據中最近更改的內容,根據需要更新它,讓視圖(單元格)聽取該屬性並相應地更新其樣式。因爲它重新接線時的項目/指標變化 – kleopatra

回答

1

合作者:

  • 上的數據側,(視圖)模型,該模型具有recentlyChanged屬性,每當值改變
  • 上觀看側,偵聽到自定義單元,其的經更新這recentlyChanged財產,並更新其適當

棘手的部分是清理電池狀態重新使用或不使用時的風格:這總是方法(!希望)被稱爲是cell.updateIndex(int newIndex),所以這是地方非/ registe聽衆。

下面可運行(儘管原油;)例如

import java.util.logging.Logger; 
import java.util.stream.Collectors; 
import java.util.stream.Stream; 

import de.swingempire.fx.util.FXUtils; 
import javafx.animation.KeyFrame; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.beans.property.ReadOnlyBooleanProperty; 
import javafx.beans.property.ReadOnlyBooleanWrapper; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class TableCoreRecentlyChanged extends Application { 

    public static class RecentChanged extends TableCell<Dummy, String> { 

     private ChangeListener<Boolean> recentListener = (src, ov, nv) -> updateRecentStyle(nv); 
     private Dummy lastDummy; 

     /* 
     * Just to see any effect. 
     */ 
     protected void updateRecentStyle(boolean highlight) { 
      if (highlight) { 
       setStyle("-fx-background-color: #99ff99"); 
      } else { 
       setStyle("-fx-background-color: #009900"); 
      } 
     } 

     @Override 
     public void updateIndex(int index) { 
      if (lastDummy != null) { 
       lastDummy.recentlyChangedProperty().removeListener(recentListener); 
       lastDummy = null; 
      } 
      updateRecentStyle(false); 
      super.updateIndex(index); 
      if (getTableRow() != null && getTableRow().getItem() != null) { 
       lastDummy = getTableRow().getItem(); 
       updateRecentStyle(lastDummy.recentlyChangedProperty().get()); 
       lastDummy.recentlyChangedProperty().addListener(recentListener); 
      } 
     } 

     @Override 
     protected void updateItem(String item, boolean empty) { 
      if (item == getItem()) return; 

      super.updateItem(item, empty); 

      if (item == null) { 
       super.setText(null); 
       super.setGraphic(null); 
      } else { 
       super.setText(item); 
       super.setGraphic(null); 
      } 
     } 

    } 

    private Parent getContent() { 
     TableView<Dummy> table = new TableView<>(createData(50)); 
     table.setEditable(true); 

     TableColumn<Dummy, String> column = new TableColumn<>("Value"); 
     column.setCellValueFactory(c -> c.getValue().valueProperty()); 
     column.setCellFactory(e -> new RecentChanged()); 
     column.setMinWidth(200); 
     table.getColumns().addAll(column); 

     int editIndex = 20; 

     Button changeValue = new Button("Edit"); 
     changeValue.setOnAction(e -> { 
      Dummy dummy = table.getItems().get(editIndex); 
      dummy.setValue(dummy.getValue()+"x"); 
     }); 
     HBox buttons = new HBox(10, changeValue); 
     BorderPane content = new BorderPane(table); 
     content.setBottom(buttons); 
     return content; 
    } 

    private ObservableList<Dummy> createData(int size) { 
     return FXCollections.observableArrayList(
       Stream.generate(Dummy::new) 
       .limit(size) 
       .collect(Collectors.toList())); 
    } 

    private static class Dummy { 
     private static int count; 

     ReadOnlyBooleanWrapper recentlyChanged = new ReadOnlyBooleanWrapper() { 

      Timeline recentTimer; 
      @Override 
      protected void invalidated() { 
       if (get()) { 
        if (recentTimer == null) { 
         recentTimer = new Timeline(new KeyFrame(
           Duration.millis(2500), 
           ae -> set(false))); 
        } 
        recentTimer.playFromStart(); 
       } else { 
        if (recentTimer != null) recentTimer.stop(); 
       } 
      } 

     }; 
     StringProperty value = new SimpleStringProperty(this, "value", "initial " + count++) { 

      @Override 
      protected void invalidated() { 
       recentlyChanged.set(true); 
      } 

     }; 

     public StringProperty valueProperty() {return value;} 
     public String getValue() {return valueProperty().get(); } 
     public void setValue(String text) {valueProperty().set(text); } 
     public ReadOnlyBooleanProperty recentlyChangedProperty() { return recentlyChanged.getReadOnlyProperty(); } 
     public String toString() {return "[dummy: " + getValue() + "]";} 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     primaryStage.setScene(new Scene(getContent())); 
    // primaryStage.setTitle(FXUtils.version()); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @SuppressWarnings("unused") 
    private static final Logger LOG = Logger 
      .getLogger(TableCoreRecentlyChanged.class.getName()); 
} 
+0

謝謝,我會根據此示例嘗試實施它,然後將其標記爲答案或評論,如果我將面對一些問題,我將無法解決我自己。 –

+0

這適用於我,我能夠在我的解決方案中使用它,並突出顯示工作。你爲我節省了很多時間。 –

+0

當我使用這個解決方案時,唯一的問題是當你運行應用程序和一些單元格更新時,它突出顯示屏幕上的內容,當我向下滾動時,那些已更新值但不是樣式。一旦我再次向下滾動,一切正常。我認爲現在需要爲所有行運行updateIndex來工作。 –

相關問題