表中的数据更新时,选定的行将被清除

时间:2019-07-15 06:41:44

标签: java javafx tableview

我已经用JavaFX创建了一个TableView,并且注意到当我选择一行时,一旦表中的项目被更新,即存储在项目中的数据被更新,选择就被清除。我创建了一个最小的示例,可以从您的工作空间运行它。在代码中,我拥有Main类,该类创建UI,将数据添加到表中,然后生成一个随机字符串,该字符串用于替换旧值,具体取决于表行的ID。我也有包含表视图模型的Person类。

我尝试存储选定的行,然后在选定内容清除后立即再次选择它,但这似乎不是可行的解决方案,而更像是hack。

主类:

public class Main extends Application
{

  private TableView<Person> table = new TableView<Person>();

  @Override
  public void start(Stage primaryStage) throws Exception
  {
    Scene scene = new Scene(new Group());
    primaryStage.setTitle("Table View Sample");
    primaryStage.setWidth(450);
    primaryStage.setHeight(500);

    final Label label = new Label("Address Book");
    label.setFont(new Font("Arial", 20));

    table.setEditable(true);

    TableColumn<Person, Integer> IDCol = new TableColumn<>("ID");
    IDCol.setMinWidth(100);
    IDCol.setCellValueFactory(new PropertyValueFactory<Person, Integer>("ID"));

    TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
    lastNameCol.setMinWidth(100);
    lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));

    table.getColumns().add(IDCol);
    table.getColumns().add(lastNameCol);

    final VBox vbox = new VBox();
    vbox.setSpacing(5);
    vbox.setPadding(new Insets(10, 0, 0, 10));
    vbox.getChildren().addAll(label, table);

    ((Group) scene.getRoot()).getChildren().addAll(vbox);

    primaryStage.setScene(scene);
    primaryStage.show();

    addDataToTable();
  }

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

  private void addDataToTable()
  {    
    //If the table has data in it, then we must check if the ID already exist, so that we can replace it.
    //else, we just add the items to the table in the first run.
    Runnable runnable = new Runnable()
    {

      @Override
      public void run()
      {
        while(true)
        {
          ObservableList<Person> data = generateData();
          try
          {
            Thread.sleep(2000);
          } catch (InterruptedException e)
          {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }

          if(table.getItems().size() > 0)
          {
            //first we cycle through the data in the generated list
            //then we cycle through the data in the table itself.
            //if the data is found, we replace it, and break from the loop.
            for(int i = 0; i < data.size(); i++)
            {
              for(int j = 0; j < table.getItems().size(); j++)
              {
                Person newPerson = data.get(i);
                Person currentPerson = table.getItems().get(j);

                if(newPerson.getID() == currentPerson.getID())
                {
                  final int J = j;
                  //now we replace it if it is the same
                  Platform.runLater(new Runnable()
                  {

                    @Override
                    public void run()
                    {
                      table.getItems().set(J, newPerson);
                    }
                  });

                  break;
                }
              }
            }
          }
          else
          {
            //When modifying the data on the table,w e do it on the platform thread, 
            //to avoid any concurrent modification exceptions.
            Platform.runLater(new Runnable()
            {

              @Override
              public void run()
              {
                table.getItems().addAll(data);
              }
            });
          }
        }
      }
    };

    Thread thread = new Thread(runnable);
    thread.setDaemon(true);
    thread.start();
  }

  private ObservableList<Person> generateData()
  {
    ObservableList<Person> values = FXCollections.observableArrayList();

    for(int i = 0; i < 100; i++)
    {
      Person oPerson = new Person(i, randomStringGeneerator());
      values.add(oPerson);
    }

    return values;
  }

  private String randomStringGeneerator()
  {
      String[] sample = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");
      String result = "";
      Random oRandom = new Random();

      int length = oRandom.nextInt(10) + 5;
      for(int i = 0 ; i < length; i++)
      {
        result += sample[oRandom.nextInt(sample.length)];
      }

      return result;
  }  
}

Person类:

public class Person
{
  private final SimpleIntegerProperty ID;
  private final SimpleStringProperty lastName;

  public Person(int ID, String lName)
  {
    this.ID = new SimpleIntegerProperty(ID);
    this.lastName = new SimpleStringProperty(lName);
  }

  public int getID()
  {
    return this.ID.get();
  }

  public void setID(int ID)
  {
    this.ID.set(ID);
  }

  public String getLastName()
  {
    return this.lastName.get();
  }

  public void setLastName(String lName)
  {
    this.lastName.set(lName);
  }

  @Override
  public String toString()
  {
    return "ID: " + ID + " value: " + lastName;
  }
}

我希望即使更新表行中的值后,该行也应保持选中状态。

1 个答案:

答案 0 :(得分:0)

因此似乎可以解决此问题,与尝试重新选择行相比,它不算什么黑客。 替换:

table.getItems().set(J, newPerson);

具有:

table.getItems().get(J).setLastName(newPerson.getLastName());
table.refresh();

因此,设置属性的值,更新模型中的数据,然后我们进行刷新,然后重新绘制UI。这不是最佳解决方案,但仍然是解决方案。