我已经用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;
}
}
我希望即使更新表行中的值后,该行也应保持选中状态。
答案 0 :(得分:0)
因此似乎可以解决此问题,与尝试重新选择行相比,它不算什么黑客。 替换:
table.getItems().set(J, newPerson);
具有:
table.getItems().get(J).setLastName(newPerson.getLastName());
table.refresh();
因此,设置属性的值,更新模型中的数据,然后我们进行刷新,然后重新绘制UI。这不是最佳解决方案,但仍然是解决方案。