有沒有一種方法可以確定列表視圖的第一個和最後一個可見行?換句話說,我正在尋找兩個索引到一個數組中,該數組填充了一個代表'顯示窗口'的頂部和底部行的列表視圖。javafx 8 listview第一行和最後一行
回答
你可以得到ListView的VirtualFlow,它具有獲取第一行和最後一行的方法。
例子:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.scene.Scene;
import javafx.scene.control.IndexedCell;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import com.sun.javafx.scene.control.skin.VirtualFlow;
public class ListViewSample extends Application {
@Override
public void start(Stage stage) {
VBox box = new VBox();
ListView<Integer> list = new ListView<>();
ObservableList<Integer> items = FXCollections.observableArrayList();
for(int i=0; i < 100; i++) {
items.add(i);
}
list.setItems(items);
box.getChildren().add(list);
VBox.setVgrow(list, Priority.ALWAYS);
Scene scene = new Scene(box, 200, 200);
stage.setScene(scene);
stage.show();
VirtualFlow flow = (VirtualFlow) list.lookup(".virtual-flow");
flow.addEventFilter(Event.ANY, event -> {
IndexedCell first = flow.getFirstVisibleCellWithinViewPort();
IndexedCell last = flow.getLastVisibleCellWithinViewPort();
System.out.println(list.getItems().get(first.getIndex()) + " - " + list.getItems().get(last.getIndex()));
});
}
public static void main(String[] args) {
launch(args);
}
}
您在控制檯中看到的完全可見的第一個和最後一個項目。
PS:我離開沒有數據校驗和事件處理你
沒有CSS查找替代版本:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.IndexedCell;
import javafx.scene.control.ListView;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import com.sun.javafx.scene.control.skin.VirtualFlow;
public class ListViewSample extends Application {
ListView<String> list = new ListView<String>();
@Override
public void start(Stage stage) {
VBox box = new VBox();
ListView<Integer> list = new ListView<>();
ObservableList<Integer> items = FXCollections.observableArrayList();
for(int i=0; i < 100; i++) {
items.add(i);
}
list.setItems(items);
box.getChildren().add(list);
VBox.setVgrow(list, Priority.ALWAYS);
Scene scene = new Scene(box, 200, 200);
stage.setScene(scene);
stage.show();
VirtualFlow virtualFlow = null;
for(Node node: list.getChildrenUnmodifiable()) {
if(node instanceof VirtualFlow) {
virtualFlow = (VirtualFlow) node;
}
}
final VirtualFlow flow = virtualFlow;
flow.addEventFilter(Event.ANY, event -> {
IndexedCell first = flow.getFirstVisibleCellWithinViewPort();
IndexedCell last = flow.getLastVisibleCellWithinViewPort();
System.out.println(list.getItems().get(first.getIndex()) + " - " + list.getItems().get(last.getIndex()));
});
}
public static void main(String[] args) {
launch(args);
}
}
UPDATE
VirtualFlow後纔可用ListView已被渲染,因爲它使用佈局參數,直到ListView在st上可見後纔可用年齡。所以我必須在確定ListView已經被渲染時確保我獲得了VirtualFlow。由於我是操縱各種方法列表我在每個方法的末尾調用此方法:
private VirtualFlow flow;
private void updateListView(int centreIndex) {
if (flow == null)
flow = (VirtualFlow) myListView.lookup(".virtual-flow");
if (flow != null){
IndexedCell first = flow.getFirstVisibleCellWithinViewPort();
IndexedCell last = flow.getLastVisibleCellWithinViewPort();
System.out.println(first.getIndex() + " - " + last.getIndex());
}
// Now the list can be selectively 'redrawn' using the scollTo() method,
// and using the .getSelectionModel().select(centreIndex) to set the
// desired cell
}
這是一個黑客一點,但它的工作原理。使用佈局參數確實有一個缺點,但需要考慮。如果ListView的高度僅比所有行的總高度小1個像素,則會看到n行,但流程會報告n-1行,這些行起初會顯示爲差異。因此保持固定的佈局高度是勢在必行的。至少現在通過使用scrollTo(..)我可以控制列表中選定項目的位置(當項目在列表中拖動時,我想保持它在列表顯示中居中)。這種解決方案讓我感到不安,但它似乎是唯一的「簡單」方式。
只是一個注意奇怪的邏輯。在程序繼續執行的過程中,獲取流程似乎需要時間。第二個(flow!= null)是避免NullPointerException所必需的。
如果你不需要它們是完全可見的,你可能還想嘗試getFirstVisibleCell()和getLastVisibleCell()。 – Roland
更新2
我的黑客事實證明不起作用。整個黑客依賴於時間。渲染是在不同的線程上完成的,一旦我改變了應用中類的實例化順序,我又一次得到了NullPointerException。我轉向Java文檔:
「JavaFX不是線程安全的,所有JavaFX操作都應該在JavaFX處理線程上運行。如果允許JavaFX應用程序與除主處理線程之外的其他線程交互,那麼不可預知的錯誤會發生「
他們這樣做!所以忘了上述 - 它不工作,並會讓你撓頭(以及更多!)試圖調試它;-)
- 1. 丟掉第一行和最後n行
- 2. 第n行到最後一行之和
- 3. 最後一行到第一行
- 4. VBA - 查找重複文本的第一行和最後一行
- 5. Android ListView:檢測滾動完成後第一行/最後一行是否可見
- 6. MYSQL,返回單行JOIN中的第一行和最後一行
- 7. 從一個表中獲取第一行和最後一行
- 8. Android listview第一行
- 9. 用第二行到最後一行的數據更新最後一行
- 10. 僅匹配第一行和最後一行的文本?
- 11. 如何替換Notepad ++中的第一行和最後一行?
- 12. 讀取文件中的第一行和最後一行
- 13. r導入csv跳過第一行和最後一行
- 14. 在VBA中同時選擇第一行和最後一行
- 15. AWK打印第一行和實例的最後一行
- 16. 從文件中刪除第一行和最後一行
- 17. 正則表達式來替換第一行和最後一行?
- 18. 排除來自SED/START /,/ END第一行和最後一行/
- 19. 如何去掉第一行和最後一行中的Android
- 20. 查詢獲取表中的第一行和最後一行
- 21. 在Excel中比較第一行和最後一行的值
- 22. VBA使用數據識別第一行和最後一行
- 23. 顯示文本文件的第一行和最後一行?
- 24. SQL查詢過濾掉第一行和最後一行
- 25. 確定第一行的最後一個flexbox和最後一行的第一個flexbox
- 26. 最小化的ListView一行成一行
- 27. Listview無法選擇最後一行
- 28. 如何獲得四行顯示的第一行和最後一行數
- 29. MySQL的獲得第一和最後一行的數據分組
- 30. 降第一和最後一行從各組
偉大的解決方案 - 謝謝你羅蘭。我正在加快JavaFX8的速度,但我沒有聽說過VirtualFlow。我有幾本關於JavaFX的書,但沒有提到VirtualFlow。即使使用谷歌搜索這個主題帶來了驚人的結果。所以,感謝你的啓發。 – Frank
我也沒有。只需進入JavaFX的源代碼,你會發現比任何書都能顯示更多的東西;-) – Roland
我可以再問一個關於此的問題嗎?運行你的例子後,我想「是的,就是這樣」。但是快樂是短暫的。一旦我將它添加到我的應用程序中,我一直得到NullPointerExceptions。所以回到Google試圖找出原因。那是當我發現這個: 答案的要點是你需要訪問TableViewSkin的VirtualFlow成員。這並不像聽起來那麼簡單,因爲皮膚在CSS解析之前不會被加載。我添加了一個Listener到TableView的skinProperty,並且能夠以這種方式獲得VirtualFlow。 仍在搜索流..... ;-) – Frank