2013-06-24 57 views
7

我使用活躍的排序和新行每毫秒的插入JavaFX的實現代碼如下...JavaFX的泰伯維保留在當前視圖中選擇行

我想這個功能:

如果我選擇了一排,然後它應該保持可見(即不應該從我的表的當前可見部分向上或向下)插入新行時。

+0

到目前爲止你試過了什麼? –

+0

table.scrollto(selectedindex) 但它不會允許滾動,如果選擇了某些東西... – learner

回答

7

這可能是很長的一段時間,它是一種駭人聽聞的,但當我需要做類似的事情時它對我有用。

答案的要點是您需要訪問的VirtualFlow成員。這並不像聽起來那麼簡單,因爲皮膚在CSS解析之前不會被加載。我向TableViewskinProperty添加了Listener,並且能夠以這種方式獲得VirtualFlow

tableView.skinProperty().addListener(new ChangeListener<Skin>() 
{ 
    @Override 
    public void changed(ObservableValue<? extends Skin> ov, Skin t, Skin t1) 
    { 
     if (t1 == null) { return; } 

     TableViewSkin tvs = (TableViewSkin)t1; 
     ObservableList<Node> kids = tvs.getChildrenUnmodifiable(); 

     if (kids == null || kids.isEmpty()) { return; } 
     flow = (VirtualFlow)kids.get(1); 
    } 
}); 

後你有VirtualFlow,你可以聽表的ObservableList更改和檢查,以確保所選擇的項目仍然在視口中。

countries.addListener(new ListChangeListener<Country>() 
{ 
    @Override 
    public void onChanged(ListChangeListener.Change<? extends Country> change) 
    { 
     while (change.next()) 
     { 
      if (change.wasAdded()) 
      { 
      if (flow == null) { return; } 
      int first = flow.getFirstVisibleCell().getIndex(); 
      int last = flow.getLastVisibleCell().getIndex(); 
      int selected = tableView.getSelectionModel().getSelectedIndex(); 

      if (selected < first || selected > last) 
      { 
       flow.show(selected); 
      } 
      } 
     } 
    } 
}); 

仍然會有一些簿記管理。例如,如果你想把焦點放回桌子上。另外,值得注意的是,VirtualFlow沒有被表格的可見矩形嚴格限制,所以即使它僅在視口之外,也可以將其視爲可見。你可以學習VirtualFlow瞭解更多詳情。

這是一個SSCCE。

JavaFXApplication21.java:

package javafxapplication21; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class JavaFXApplication21 extends Application 
{ 
    @Override 
    public void start(Stage stage) throws Exception 
    { 
     Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml")); 

     Scene scene = new Scene(root); 

     stage.setScene(scene); 
     stage.show(); 
    } 

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

Sample.fxml:

<?xml version="1.0" encoding="UTF-8"?> 

<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<AnchorPane id="AnchorPane" prefHeight="200.0" prefWidth="200.0" xmlns:fx="http://javafx.com/fxml" fx:controller="javafxapplication21.SampleController"> 
    <children> 
    <ToolBar AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> 
     <items> 
     <Button fx:id="insertBtn" mnemonicParsing="false" text="Insert" /> 
     </items> 
    </ToolBar> 
    <TableView fx:id="tableView" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="31.0"> 
     <columns> 
     <TableColumn prefWidth="100.0" text="Country" fx:id="countryColumn" /> 
     <TableColumn prefWidth="100.0" text="Capital" fx:id="capitalColumn" /> 
     </columns> 
    </TableView> 
    </children> 
</AnchorPane> 

SampleController.java:

package javafxapplication21; 

import com.sun.javafx.scene.control.skin.TableViewSkin; 
import com.sun.javafx.scene.control.skin.VirtualFlow; 
import java.net.URL; 
import java.util.*; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.*; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.scene.Node; 
import javafx.scene.control.*; 
import javafx.scene.control.cell.PropertyValueFactory; 

public class SampleController implements Initializable 
{ 
    @FXML private Button insertBtn; 
    @FXML private TableView<Country> tableView; 
    @FXML private TableColumn<Country, String> countryColumn; 
    @FXML private TableColumn<Country, String> capitalColumn; 

    private VirtualFlow flow; 

    private ObservableList<Country> countries = 
      FXCollections.observableArrayList(); 
    private List<Country> insertList = new ArrayList<>(); 

    public SampleController() 
    { 
     countries.addAll(new Country("AG", "Buenos Aires"), 
       new Country("AU", "Vienna"), 
       new Country("BY", "Minsk"), 
       new Country("CO", "Bogota"), 
       new Country("EG", "Cairo")); 

     insertList.add(new Country("ZI", "Harare")); 
     insertList.add(new Country("UK", "London")); 
     insertList.add(new Country("TW", "Taipei")); 
    } 

    @Override 
    public void initialize(URL url, ResourceBundle rb) 
    { 
     countryColumn.setCellValueFactory(
       new PropertyValueFactory<Country, String>("name")); 
     capitalColumn.setCellValueFactory(
       new PropertyValueFactory<Country, String>("capital")); 

     tableView.setItems(countries); 

     tableView.skinProperty().addListener(new ChangeListener<Skin>() 
     { 
      @Override 
      public void changed(ObservableValue<? extends Skin> ov, 
       Skin t, Skin t1) 
      { 
       if (t1 == null) { return; } 

       TableViewSkin tvs = (TableViewSkin)t1; 
       ObservableList<Node> kids = tvs.getChildrenUnmodifiable(); 

       if (kids == null || kids.isEmpty()) { return; } 

       flow = (VirtualFlow)kids.get(1); 
      } 
     }); 

     insertBtn.setOnAction(new EventHandler<ActionEvent>() 
     { 
      @Override 
      public void handle(ActionEvent t) 
      { 
       if (!insertList.isEmpty()) 
       { 
        countries.add(2, insertList.get(0)); 
        insertList.remove(0); 
       } 
      } 
     }); 

     countries.addListener(new ListChangeListener<Country>() 
     { 
      @Override 
      public void onChanged(ListChangeListener.Change<? extends Country> change) 
      { 
       while (change.next()) 
       { 
        if (change.wasAdded()) 
        { 
         if (flow == null) { return; } 
         int first = flow.getFirstVisibleCell().getIndex(); 
         int last = flow.getLastVisibleCell().getIndex(); 
         int selected = tableView.getSelectionModel().getSelectedIndex(); 

         if (selected < first || selected > last) 
         { 
          flow.show(selected); 
         } 
        } 
       } 
      } 
     }); 
    } 

    public class Country 
    { 
     private SimpleStringProperty name; 
     private SimpleStringProperty capital; 

     public Country(String name, String capital) 
     { 
      this.name = new SimpleStringProperty(name); 
      this.capital = new SimpleStringProperty(capital); 
     } 

     public SimpleStringProperty nameProperty() { return name; } 
     public SimpleStringProperty capitalProperty() { return capital; } 
    } 
} 
1

我也有。你可以使用cellEventHandler類同樣的問題當在表格中選擇一個單元格並設置最後選定的行索引時,它將實施EventHandler接口到一個變量。課程如下。

public class CellEventHandler implements EventHandler<MouseEvent> 

{ 
    CellEventHandler() 
    { 
    } 

    @Override 
    public void handle(MouseEvent t) 
    { 
     TableCell c; 
     c = (TableCell) t.getSource(); 
     c.getIndex(); 
     PanelController.selectedItem = c.getIndex(); 
    } 
}` 

然後,您在TableController類中表的表類呈現應該如下所示。

typeCol.setCellFactory(new Callback<TableColumn<tableModel, String>, TableCell<tableModel, String>>() 
    { 
     @Override 
     public TableCell<tableModel, String> call(TableColumn<tableModel, String> tableColumn) 
     { 
      LableCell lableCell = new LableCell(Pos.CENTER, true); 
      lableCell.addEventFilter(MouseEvent.MOUSE_CLICKED, new CellEventHandler()); 
      return lableCell; 
     } 
    }); 

的「selectedItem屬性」欄應在panelController類的靜態字段來聲明,然後說:「將selectedItem」應該設置如表中選擇的,當刷新錶行數據。

myTable.getSelectionModel().select(selectedItem);