Javafx 树视图困境

Javafx 树视图困境,javafx,Javafx,我有一个数据模型: 客户-名称 在客户端对象类中声明的映射 客户 -标题-价值 -标题-价值 -标题-价值 客户 -标题-价值 -标题-价值 -标题-价值 据我所知,TreeTableView必须只遵循一种数据类型是否有办法使其同时包含客户端和Map或者我是被迫将Map作为客户端的一部分? JavaTuple的使用会起作用吗 public TreeTableView createContent() { TreeItem<String> root = new TreeItem

我有一个数据模型:
客户-名称
在客户端对象类中声明的映射

客户
-标题-价值
-标题-价值
-标题-价值
客户
-标题-价值
-标题-价值
-标题-价值

据我所知,
TreeTableView
必须只遵循一种数据类型是否有办法使其同时包含客户端和
Map
或者我是被迫将
Map
作为客户端的一部分?
JavaTuple的使用会起作用吗

public TreeTableView createContent() {

    TreeItem<String> root = new TreeItem<>();
    //treeTableView.setRoot(root);
    root.setExpanded(true);
    //final TreeItem<String> rootItem = new TreeItem<>();
    ArrayList<TreeItem<String>> rootList = new ArrayList<TreeItem<String>>();
    ArrayList<TreeItem<String>> titleList = new ArrayList<TreeItem<String>>();
    ArrayList<TreeItem<String>> valueList = new ArrayList<TreeItem<String>>();
    TreeItem<String> rootItem = new TreeItem<>();

        for(Client client:clients){
            rootItem = new TreeItem<>(client.getName());//.getName());
        //rootItem.setValue(client.getName());//nameProperty().getValue());
        rootList.add(rootItem);
    }  

        for(Entry<Title, DoubleProperty> map1:map.entrySet()){
            final TreeItem<Entry<Title, DoubleProperty>> mapItem = new TreeItem<>(map1);//.getKey(),map1.getValue());
            final TreeItem<String> child2Item = new TreeItem<>(map1.getKey().getName());//, map1.getValue().getValue().toString());
            final TreeItem<String> child3Item = new TreeItem<>(map1.getValue().getValue().toString());
            titleList.add(child2Item); 
            valueList.add(child3Item);
        }

        /*for(Title title:titles){
            //final TreeItem child1Item = new TreeItem<>(client.getValue(title));
            final TreeItem<String> child2Item = new TreeItem<>(title.getName());//title.getName());
        titleList.add(child2Item); 
        }*/

        for(TreeItem<String> root1:rootList){
            root.getChildren().add(root1);
            for(TreeItem<String> title1:titleList){
            root1.getChildren().add(title1);
        }
            for(TreeItem<String> value:valueList){
                root1.getChildren().add(value);
            }
        }

    // Name column
    final TreeTableColumn<Client, String> nameColumn = new TreeTableColumn<>("Name");
    nameColumn.setEditable(false);
    nameColumn.setMinWidth(150);
    //nameColumn.setCellValueFactory( new TreeItemPropertyValueFactory<Client, String>("value") );
    nameColumn.setCellValueFactory(//param -> param.getValue().getValue().nameProperty());
            new Callback<TreeTableColumn.CellDataFeatures<Client, String>, ObservableValue<String>>() {
        @Override
        public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<Client, String> p) {
            return new ReadOnlyObjectWrapper(p.getValue().getValue());
        }
    });

    // Data column
    TreeTableColumn<Client, String> dataColumn = new TreeTableColumn<>("Values");
    dataColumn.setEditable(true);
    dataColumn.setMinWidth(50);
   // dataColumn.setCellValueFactory( new MapValueFactory<>("mapvalue");
            //new TreeItemPropertyValueFactory<Client, String>("name") );
    //dataColumn.setCellValueFactory(new TreeItemPropertyValueFactory<Client, String>("name"));
    dataColumn.setCellValueFactory(
            new Callback<TreeTableColumn.CellDataFeatures<Client, String>, ObservableValue<String>>() {
        @Override
        public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<Client, String> p) {
        return new ReadOnlyStringWrapper(p.getValue().getValue().getValues().values().toString());
}
});

    final TreeTableView<Client> treeTableView = new TreeTableView(root);//rootItem);
    treeTableView.setShowRoot(false);
    treeTableView.getColumns().add( nameColumn );
    treeTableView.getColumns().add( dataColumn );
    treeTableView.setEditable(true);
    treeTableView.setColumnResizePolicy( TreeTableView.CONSTRAINED_RESIZE_POLICY );
    treeTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    treeTableView.setPrefSize(515, 100);
    treeTableView.setLayoutX(10);
    treeTableView.setLayoutY(10);

    return treeTableView;
}
}
public TreeTableView createContent(){
TreeItem root=新的TreeItem();
//treeTableView.setRoot(root);
root.setExpanded(true);
//final TreeItem rootItem=新TreeItem();
ArrayList根列表=新的ArrayList();
ArrayList titleList=新的ArrayList();
ArrayList valueList=新的ArrayList();
TreeItem rootItem=新的TreeItem();
用于(客户端:客户端){
rootItem=newtreeitem(client.getName());//.getName());
//rootItem.setValue(client.getName());//nameProperty().getValue());
rootList.add(rootItem);
}  
对于(条目map1:map.entrySet()){
final TreeItem mapItem=new TreeItem(map1);//.getKey(),map1.getValue();
final TreeItem child2Item=new TreeItem(map1.getKey().getName());/,map1.getValue().getValue().toString());
final TreeItem child3Item=new TreeItem(map1.getValue().getValue().toString());
标题列表。添加(child2Item);
价值清单。添加(Child3项);
}
/*用于(标题:标题){
//final TreeItem child1Item=新的TreeItem(client.getValue(title));
final TreeItem child2Item=new TreeItem(title.getName());//title.getName());
标题列表。添加(child2Item);
}*/
for(TreeItem root1:rootList){
root.getChildren().add(root1);
for(树标题1:标题列表){
root1.getChildren().add(title1);
}
for(树项值:valueList){
root1.getChildren().add(value);
}
}
//名称列
final TreeTableColumn Name column=新的TreeTableColumn(“名称”);
nameColumn.setEditable(false);
nameColumn.setMinWidth(150);
//nameColumn.setCellValueFactory(新的TreeItemPropertyValueFactory(“值”));
nameColumn.setCellValueFactory(//param->param.getValue().getValue().nameProperty());
新回调函数(){
@凌驾
公共observeValue调用(TreeTableColumn.celldatap){
返回新的ReadOnlyObjectWrapper(p.getValue().getValue());
}
});
//数据列
TreeTableColumn dataColumn=新的TreeTableColumn(“值”);
dataColumn.setEditable(true);
dataColumn.setMinWidth(50);
//dataColumn.setCellValueFactory(新的MapValueFactory(“mapvalue”);
//新的TreeItemPropertyValueFactory(“名称”);
//setCellValueFactory(新的TreeItemPropertyValueFactory(“名称”);
dataColumn.setCellValueFactory(
新回调函数(){
@凌驾
公共observeValue调用(TreeTableColumn.celldatap){
返回新的ReadOnlyStringWrapper(p.getValue().getValue().getValues().values().toString());
}
});
final-TreeTableView-TreeTableView=new-TreeTableView(root);//rootItem);
treeTableView.setShowRoot(false);
treeTableView.getColumns().add(nameColumn);
treeTableView.getColumns().add(dataColumn);
treeTableView.setEditable(true);
treeTableView.setColumnResizePolicy(treeTableView.CONSTRAINED_RESIZE_策略);
treeTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
treeTableView.setPrefSize(515100);
树视图。setLayoutX(10);
树视图。设置布局(10);
返回树视图;
}
}
通过这样做,我可以直接在每个标题下获得值,而不是在第二列,我觉得我在欺骗自己,将其转换为字符串,我希望将来可以对其进行编辑,从而更改地图或客户端中的实际值

客户端对象类:

public class Client {
private final StringProperty name = new SimpleStringProperty(this, "name");
public final String getName() {
    return name.get();
}
public final void setName(String name) {
    this.name.set(name);
}
public StringProperty nameProperty() {
    return name ;
}
private final Map<Title, DoubleProperty> values = new HashMap<>();

public Client(String name) {
    setName(name);
}

public DoubleProperty valueProperty(Title title) {
    // In Java 8, just do
    // return values.computeIfAbsent(title, t -> new SimpleDoubleProperty());

    DoubleProperty value = values.get(title);
    if (value == null) {
        value = new SimpleDoubleProperty();
        values.put(title, value);
    }
    return value ;
}

public final double getValue(Title title) {
    return valueProperty(title).get();
}

public final void setValue(Title title, double value) {
    valueProperty(title).set(value);
}

public Map<Title, DoubleProperty> getValues() {
    return values ;
}
}
公共类客户端{
私有最终StringProperty名称=新SimpleStringProperty(此“名称”);
公共最终字符串getName(){
返回name.get();
}
公共最终无效集合名(字符串名){
this.name.set(name);
}
公共字符串属性nameProperty(){
返回名称;
}
私有最终映射值=新HashMap();
公共客户端(字符串名称){
集合名(名称);
}
公共财产价值财产(所有权){
//在Java8中,只需执行以下操作
//返回值.computeIfAbsent(title,t->new SimpleDoubleProperty());
DoubleProperty value=values.get(标题);
如果(值==null){
值=新的SimpleDoubleProperty();
价值。放置(标题、价值);
}
返回值;
}
公共最终双getValue(标题){
返回valueProperty(title.get();
}
公共最终无效设置值(标题标题,双值){
valueProperty(标题)。设置(值);
}
公共映射getValues(){
返回值;
}
}

当我最初建议一个表格时,你的客户标题图就是这样的。我假设您希望以这种方式显示数据。这可能不是最好的办法


如果您只显示字符串,那么很容易在cellValueFactory中提供您自己的字符串。然而,我刚刚尝试使用
是否要将
标题
添加到同一个节点?否,我希望标题显示为客户端父节点下的子节点,值显示在第二列中,请让我添加一些代码以显示我在mmaybe中的内容。我没有正确解释我自己,我有一个类对象标题,它将被所有节点固定客户机说有3个都必须有它们,但是当通过客户机中的setvalue设置它们时,每个客户机的值都不同。我正在努力将每个客户端的地图数据检索到treeview中。像这样存储在客户机对象类中
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TextFieldTreeTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.converter.NumberStringConverter;

public class StackedTTV extends Application {

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

    @Override
    public void start(Stage stage) {
        final ObservableList<XYChart.Series<String, Number>> chartdata = FXCollections.observableArrayList();
        final CategoryAxis xAxis = new CategoryAxis(
                FXCollections.observableArrayList("Wait","Agreed","Work"));
        for (int i = 0; i < 4; i++) {
            chartdata.add(new XYChart.Series<>("Test"+i, FXCollections.observableArrayList(
                    new XYChart.Data(xAxis.getCategories().get(0), 1000),
                    new XYChart.Data(xAxis.getCategories().get(1), 1000),
                    new XYChart.Data(xAxis.getCategories().get(2), 1000)
            )));
        }
        final StackedBarChart sbc = new StackedBarChart(xAxis, new NumberAxis(), chartdata);

        final TreeTableView<XYChart.Data<String, Number>> ttv = new TreeTableView<>(
                new TreeItem<XYChart.Data<String,Number>>(new XYChart.Data<>()));
        ttv.setShowRoot(false);

        for (XYChart.Series<String, Number> serie: chartdata){
            TreeItem<XYChart.Data<String,Number>> ti = new TreeItem<>(new XYChart.Data<>(serie.getName(), null));
            ttv.getRoot().getChildren().add(ti);
            for (XYChart.Data<String,Number> data : serie.getData()){
                ti.getChildren().add(new TreeItem(data));
            }
        }

        TreeTableColumn<XYChart.Data<String,Number>,String> clientCol = new TreeTableColumn<>("client");
        clientCol.setCellValueFactory((param) -> {
            return param.getValue().isLeaf() 
                    ? new SimpleStringProperty("")
                    : param.getValue().getValue().XValueProperty();
        });
        clientCol.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn());
        clientCol.setOnEditCommit((evt) ->{
            if (evt.getRowValue().isLeaf()) return;
            for (XYChart.Series serie: chartdata){
                if (serie.getName().equals(evt.getOldValue()))
                    serie.setName(evt.getNewValue());
            }
            evt.getRowValue().getValue().setXValue(evt.getNewValue());
        });

        TreeTableColumn<XYChart.Data<String,Number>,String> titleCol = new TreeTableColumn<>("title");
        titleCol.setCellValueFactory((param) -> {
            return param.getValue().isLeaf() 
                    ? param.getValue().getValue().XValueProperty()
                    : new SimpleStringProperty("");
        });
        titleCol.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn());
        titleCol.setOnEditCommit((evt) -> {
            final String ov = evt.getOldValue();
            final String nv = evt.getNewValue();
            //change the name for all series
            for (XYChart.Series<String, Number> serie : chartdata)
                for (XYChart.Data<String, Number> data : serie.getData())
                    if(ov.equals(data.getXValue()))  data.setXValue(nv);
            xAxis.getCategories().set(xAxis.getCategories().indexOf(ov),nv);
            //chart is confused as to which categories to listen to
            //System.out.println(sbc.getXAxis().getTickMarks());
        });

        TreeTableColumn<XYChart.Data<String,Number>,Number> valueCol = new TreeTableColumn<>("value");
        valueCol.setCellValueFactory((param) -> {
            return param.getValue().getValue().YValueProperty();
        });
        valueCol.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn(new NumberStringConverter()));
        valueCol.setOnEditCommit((evt) ->{
            evt.getRowValue().getValue().setYValue(evt.getNewValue());
        });

        ttv.getColumns().addAll(clientCol,titleCol,valueCol);
        ttv.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
        ttv.getSelectionModel().setCellSelectionEnabled(true);
        ttv.setEditable(true);

        final TextField txt = new TextField();
        txt.setPromptText("new title");
        txt.setOnAction((evt)->{
            //add to category axis
            //todo - check for dup
            xAxis.getCategories().add(txt.getText());
            //add new title to each series with 1000 and to table
            for (XYChart.Series<String, Number> serie : chartdata) {
                XYChart.Data<String, Number> newdata = new XYChart.Data<>(txt.getText(), 1000);
                serie.getData().add(newdata);
                for(TreeItem<XYChart.Data<String,Number>> ti:  ttv.getRoot().getChildren()){
                    if(ti.getValue().XValueProperty().get().equals(serie.getName())){
                        ti.getChildren().add(new TreeItem<>(newdata));
                    }
                }
            }
        });
        final VBox sceneRoot = new VBox(ttv,sbc,txt);
        final Scene scene = new Scene(sceneRoot);
        stage.setScene(scene);
        stage.show();
    }
}