我的布局基本上由ChoiceBox
和TableView
组成。我想要实现的是根据TableView
中选定的选项在ChoiceBox
中显示不同的数据。
到目前为止我所拥有的是:
MainController 类:
private void configureChoiceBox() {
choiceBox.getSelectionModel().selectedIndexProperty().addListener((v, oldValue, newValue) -> {
if(newValue.intValue() == 0) {
workshopList.setItems(data.getPipeCableList());
}
else if(newValue.intValue() == 1) {
workshopList.setItems(data.getElementList());
}
});
}
数据类:
private ObservableList<PipeCable> pipeCableList;
private ObservableList<Element> elementList;
/**/
private ObservableList<StoredItem> displayedList;
public Data() {
this.pipeCableList = FXCollections.observableArrayList();
this.elementList = FXCollections.observableArrayList();
/**/
this.displayedList = FXCollections.observableArrayList();
}
public ObservableList<StoredItem> getPipeCableList() {
displayedList.removeAll(elementList);
displayedList.addAll(pipeCableList);
return displayedList;
}
public ObservableList<StoredItem> getElementList() {
displayedList.removeAll(pipeCableList);
displayedList.addAll(elementList);
return displayedList;
}
问题是:当我在ChoiceBox
中的选项之间进行更改时,来自elementList
和pipeCableList
的数据混合在一起并更改{{1}中的选项没有任何结果。
我想要实现的目标:根据{{1}选择的选项,能够显示ChoiceBox
和elementList
中包含的不同数据}。而且,当选择一个选项(显示一个列表)时,添加到该列表的所有新项目将在pipeCableList
上可见。
编辑(添加缺失信息): ChoiceBox
和TableView
延伸PipeCable
,Element
获取StoredItem
类型的项目。
答案 0 :(得分:1)
出了什么问题
摆脱displayList,TableView已经引用了它显示的项目列表,所以只需将其设置为适当的列表即可。目前,您的显示列表值与基础数据值不同步。
假设
我假设您的TableView采用StoredItem类型的项目,并且PipeCable和Element也是StoredItem类型(尽管继承或接口实现)。
如何解决
通常,您可以这样做:
tableView.setItems(data.getPipeCableList())
选择时,和元素列表相同。但由于Java泛型的一些限制,我似乎无法轻易绕过,但这不能编译。如果元素列表和管道电缆列表都是相同的类型(而不是普通父类型的子元素),那就不会有问题。
要解决泛型问题,您可以:
tableView.getItems().setAll(data.getPipeCableList())
哪个工作正常,但如果数据项发生更改,则不会使表视图项与数据项保持同步。
为了使这些保持同步,你可以这样做:
Bindings.bindContent(tableView.getItems(), data.getPipeCableList());
这有点难看,但似乎有用。
完整示例应用
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.stream.IntStream;
public class MultiListTable extends Application {
enum ItemType {
PipeCable, Element
}
@Override public void start(Stage stage) throws IOException {
TableView<StoredItem> tableView = new TableView<>();
TableColumn<StoredItem, String> nameColumn = new TableColumn<>("Name");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
nameColumn.setPrefWidth(120);
tableView.getColumns().add(nameColumn);
Data data = new Data();
ChoiceBox<ItemType> choiceBox = new ChoiceBox<>(
FXCollections.observableArrayList(ItemType.values())
);
choiceBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
switch (newValue) {
case PipeCable:
Bindings.bindContent(tableView.getItems(), data.getPipeCableList());
break;
case Element:
Bindings.bindContent(tableView.getItems(), data.getElementList());
break;
}
});
choiceBox.getSelectionModel().select(0);
Button addPipe = new Button("Add Pipe");
addPipe.setOnAction(event -> data.getPipeCableList().add(
new PipeCable("Pipe " + (data.getPipeCableList().size() + 1))
));
IntStream.range(0, 3).forEach(i -> addPipe.fire());
Button addElement = new Button("Add Element");
addElement.setOnAction(event -> data.getElementList().add(
new Element("Element " + (data.getElementList().size() + 1))
));
IntStream.range(0, 2).forEach(i -> addElement.fire());
HBox controls = new HBox(10, choiceBox, addPipe, addElement);
VBox layout = new VBox(10, controls, tableView);
layout.setPadding(new Insets(10));
Scene scene = new Scene(layout);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
class Data {
private ObservableList<PipeCable> pipeCableList = FXCollections.observableArrayList();
private ObservableList<Element> elementList = FXCollections.observableArrayList();
ObservableList<PipeCable> getPipeCableList() {
return pipeCableList;
}
ObservableList<Element> getElementList() {
return elementList;
}
}
static public class StoredItem {
private final ReadOnlyStringWrapper name;
public StoredItem(String name) {
this.name = new ReadOnlyStringWrapper(name);
}
public String getName() {
return name.get();
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
}
static public class PipeCable extends StoredItem {
public PipeCable(String name) {
super(name);
}
}
static public class Element extends StoredItem {
public Element(String name) {
super(name);
}
}
}