我使用JavaFX TableView来显示存储在observablelist中的数据。 TableView的SelectionMode设置为multiple。我希望用户能够在列表中的数据更新时选择多行。
我的问题是,只要更改了可观察列表中的数据并且只选择了一行,就会重置选择。列表中的项目数不会更改 - 因此我不会在列表中添加或删除项目,只会更改其状态。
即使可观察列表发生变化,有没有办法保持多行选择?
我可能会在更改发生之前读出当前选择并尝试在代码中恢复选择。但是这个列表经常更新,这似乎不太有效。我希望有更好的解决方案。
P.S。:对JavaFX-Thread内部发生observablelist的更改。
这是一个显示我的问题的最小示例(选择几行并按更新按钮 - 仍然只选择最后一行):
package javafxtableviewtest;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class JavaFXTableViewTest extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
控制器:
package javafxtableviewtest;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableView;
public class FXMLDocumentController implements Initializable {
List<SomeData> dataList = new ArrayList();
private ObservableList<SomeData> observedList = FXCollections.observableArrayList(dataList);
@FXML
private Button updatButton;
@FXML
private TableView myTable;
@Override
public void initialize(URL url, ResourceBundle rb) {
for(int i = 0; i < 8; i++){
SomeData newData = new SomeData();
newData.setID(i);
newData.setStatus(0);
observedList.add(newData);
}
myTable.setItems(observedList);
myTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
}
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("Update table!");
Platform.runLater(new Runnable() {
@Override
public void run() {
Integer index = 5;
SomeData newData = new SomeData();
newData.setID(index);
newData.setStatus(observedList.get(index).getStatus() + 1);
observedList.set(index, newData);
}
});
}
}
型号:
package javafxtableviewtest;
public class SomeData {
private int ID;
private int status;
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<AnchorPane id="AnchorPane" prefHeight="684.0" prefWidth="827.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="javafxtableviewtest.FXMLDocumentController">
<children>
<Button fx:id="button" layoutX="694.0" layoutY="616.0" onAction="#handleButtonAction" text="Update" />
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
<TableView fx:id="myTable" layoutX="42.0" layoutY="30.0" prefHeight="562.0" prefWidth="707.0">
<columns>
<TableColumn editable="false" maxWidth="100.0" minWidth="20.0" prefWidth="75.0" text="ID">
<cellValueFactory><PropertyValueFactory property="ID" />
</cellValueFactory>
</TableColumn>
<TableColumn editable="false" maxWidth="100.0" minWidth="20.0" prefWidth="75.0" text="Status">
<cellValueFactory><PropertyValueFactory property="status" />
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
</children>
</AnchorPane>