我写了这个小例子应用程序:
package application; import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn.CellEditEvent; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.control.cell.TextFieldTableCell; import javafx.scene.input.MouseEvent; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class Main extends Application { public class Person { private StringProperty firstName = new SimpleStringProperty(); private StringProperty lastName = new SimpleStringProperty(); public Person(String firstName, String lastName) { this.firstName.set(firstName); this.lastName.set(lastName); } public String getFirstName() { return firstName.get(); } public String getLastName() { return lastName.get(); } public StringProperty firstNameProperty() { return firstName; } public StringProperty lastNameProperty() { return lastName; } } @Override public void start(Stage primaryStage) { try { StackPane root = new StackPane(); TableViewtv = new TableView<>(); TableColumn col = new TableColumn ("FirstName"); col.setCellValueFactory(new PropertyValueFactory ("firstName")); tv.getColumns().add(col); tv.setEditable(true); col = new TableColumn ("LastName"); col.setCellValueFactory(new PropertyValueFactory ("lastName")); col.setCellFactory(TextFieldTableCell.forTableColumn()); col.setOnEditCommit(new EventHandler >() { @Override public void handle(CellEditEvent event) { System.out.println(tv.getItems().get(1).getLastName()); } }); tv.getColumns().add(col); for (int i = 0; i < 30; i++) { tv.getItems().add(new Person("Test" + i, "Test" + i)); } root.getChildren().add(tv); Scene scene = new Scene(root, 400, 200); primaryStage.setScene(scene); primaryStage.show(); tv.addEventFilter(MouseEvent.MOUSE_RELEASED, event -> { // ... }); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); } }
我想在ScrollBar
到达底部时执行操作.然后我想从数据库重新加载更多数据.但只有这样,当用户看到所有已经加载的数据时(=底部的滚动条).你有什么好建议来解决这个问题吗?
我的第一个想法是捕捉MOUSE_RELEASED
事件(当用户拖动栏时),TableView
然后检查以下位置ScrollBar
: - getValue()获取栏的位置 - getMax()最大值(= bottom).
但我找不到一种方法(不使用通过这种方法的css选择器)来获取ScrollBar
给定的TableView
.所以我无法确定它的位置TableView
.
你有什么想法??
我很兴奋.谢谢你的帮助.
获取滚动条的唯一方法是通过查找,这有点像黑客,但只要你在场景上渲染表后就可以工作.你需要
ScrollBar verticalBar = (ScrollBar) table.lookup(".scroll-bar:vertical");
请注意,不需要弄乱用户事件:您可以直接观察滚动条的value
属性:
verticalBar.valueProperty().addListener((obs, oldValue, newValue) -> { if (newValue.doubleValue() >= verticalBar.getMax()) { // add more data... } });
SSCCE:
import java.util.ArrayList; import java.util.List; import java.util.function.Function; import javafx.application.Application; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; import javafx.concurrent.Task; import javafx.scene.Scene; import javafx.scene.control.ScrollBar; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class AddMoreTableDataOnScrollToBottom extends Application { @Override public void start(Stage primaryStage) { TableView- table = new TableView<>(); table.getColumns().add(column("Item", Item::nameProperty)); table.getColumns().add(column("Value", Item::valueProperty)); addMoreData(table, 20); Scene scene = new Scene(new BorderPane(table), 400, 400); primaryStage.setScene(scene); primaryStage.show(); ScrollBar verticalBar = (ScrollBar) table.lookup(".scroll-bar:vertical"); verticalBar.valueProperty().addListener((obs, oldValue, newValue) -> { if (newValue.doubleValue() >= verticalBar.getMax()) { addMoreData(table, 20); } }); } private void addMoreData(TableView
- table, int numItems) { Task
> dataRetrieveTask = new Task
>() { @Override public List
- call() throws Exception { // mimic connect to db: Thread.sleep(500); List
- items = new ArrayList<>(); int nextItem = table.getItems().size() + 1 ; for (int i = nextItem; i < nextItem + numItems; i++ ){ items.add(new Item("Item "+i, i)); } return items ; } }; dataRetrieveTask.setOnSucceeded(e -> table.getItems().addAll(dataRetrieveTask.getValue())); new Thread(dataRetrieveTask).start(); } private
TableColumncolumn(String title, Function> prop) { TableColumncol = new TableColumn<>(title); col.setCellValueFactory(cellData -> prop.apply(cellData.getValue())); return col ; } public static class Item { private final StringProperty name = new SimpleStringProperty(); private final IntegerProperty value = new SimpleIntegerProperty(); public Item(String name, int value) { setName(name); setValue(value); } public final StringProperty nameProperty() { return this.name; } public final String getName() { return this.nameProperty().get(); } public final void setName(final String name) { this.nameProperty().set(name); } public final IntegerProperty valueProperty() { return this.value; } public final int getValue() { return this.valueProperty().get(); } public final void setValue(final int value) { this.valueProperty().set(value); } } public static void main(String[] args) { launch(args); } }