Javafx Tableview在当前视图中保留选定的行

时间:2013-06-24 05:25:33

标签: java javafx-2 tableview

我正在使用javafx tableview,主动排序并每毫秒插入一个新行......

我想要这个功能:

如果我选择了一行,那么当插入新行时,它应该保持可见(不应该从我表格的当前可见部分向上或向下)。

3 个答案:

答案 0 :(得分:7)

这可能是它的长期存在和它的一种hackish,但当我需要做类似的事情时,它对我有用。

答案的要点是,您需要访问VirtualFlow的{​​{1}}成员。这并不像听起来那么简单,因为在解析CSS之前不会加载皮肤。我向TableViewSkin的{​​{1}}添加了Listener,并且能够以skinProperty的方式获得。{/ p>

TableView

获得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并非严格限制在表格的可见矩形中,因此即使项目位于视口之外,也可以认为该项目是可见的。您可以查看VirtualFlow了解更多详情。

这是一个SSCCE。

JavaFXApplication21.java:

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

Sample.fxml:

VirtualFlow

SampleController.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);
    }
}

答案 1 :(得分: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();
    }
}`

然后,PanelController类中的表的表类呈现应该如下所示。

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

答案 2 :(得分:0)

这对我有用:

tableView.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, t1) -> {

        TableViewSkin tvs = (TableViewSkin)tableView.getSkin();
        ObservableList<Node> kids = tvs.getChildren();

        if (kids == null || kids.isEmpty()) { return; }
        VirtualFlow flow = (VirtualFlow)kids.get(1);
        int first =-1;
        if (flow.getFirstVisibleCell() != null) first = flow.getFirstVisibleCell().getIndex();
        int last = -1;
        if (flow.getFirstVisibleCell() != null) last = flow.getLastVisibleCell().getIndex();

        if(first !=-1 && t1.intValue()<first)
            flow.scrollTo(t1.intValue());
        if(last != -1 && t1.intValue()>last)
            flow.scrollTo(t1.intValue()+1);

    });