2015-12-21 85 views
1

滾動條的位置,我已經寫了這個小示例應用程序:JavaFX的 - 如何識別一個TableView中

screenshot

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(); 

      TableView<Person> tv = new TableView<>(); 
      TableColumn<Person, String> col = new TableColumn<Person, String>("FirstName"); 
      col.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); 

      tv.getColumns().add(col); 
      tv.setEditable(true); 

      col = new TableColumn<Person, String>("LastName"); 
      col.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); 
      col.setCellFactory(TextFieldTableCell.forTableColumn()); 
      col.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() { 

       @Override 
       public void handle(CellEditEvent<Person, String> 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()最大值( =底部)。

但我找不到一個方法(不使用通過this method的css選擇器)從給定的TableView得到ScrollBar。所以我不能檢查它在某個TableView中的位置。

你有什麼想法嗎?

我很興奮。謝謝你的幫助。

+0

也許這會工作:[onScrollToColumn](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TableView.html#onScrollToColumnProperty) –

+0

對不起,脫離主題(意思是:請,只有ack如果你願意的話),你是否在你的單元格中獲得了複製效果,編輯一個單元格導致該行中的所有其他單元格都取得該值?在某些地方,我的設置和你基本相同,並且遇到了這個奇怪的問題。 –

回答

4

獲取滾動條的唯一方法是通過查找,這有點破解,但只要你這樣做,它就會工作該表已在場景中呈現。您需要

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<Item> 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<Item> table, int numItems) { 
     Task<List<Item>> dataRetrieveTask = new Task<List<Item>>() { 
      @Override 
      public List<Item> call() throws Exception { 
       // mimic connect to db: 
       Thread.sleep(500); 
       List<Item> 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 <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> prop) { 
     TableColumn<S,T> col = 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); 
    } 
} 
+0

這不起作用。即使ScrollBar存在,我也會得到空值。 –

+0

@AdamArold我發佈的SSCCE不起作用? –

+0

將'table.lookup'修改爲'table.lookupAll'。那麼它將適用於所有情況。 –