我有一个数据模型:
客户 - 姓名
在Client对象类中声明的映射。
客户端
- 标题 - 价值
- 标题 - 价值
- 标题 - 价值
客户
- 标题 - 价值
- 标题 - 价值
- 标题 - 价值
据我所知,TreeTableView
必须只遵守一种数据类型是否可以让它同时保留客户端和Map
,或者我是否被迫Map
1}}客户的一部分?
使用javatuples会发挥作用吗?
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 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 ;
}
}
答案 0 :(得分:1)
当我最初建议的表格是你的-client-title绘图的样子。我假设你想要显示数据的方式。这可能不是最好的方式。
如果您只显示字符串,那么在cellValueFactory中提供自己的字符串很容易。但是,我只是尝试使用<XYChart.Data<String, Integer>
,它可以正常使用一些技巧。
我没有使用地图或类似的东西。这就是我建议树表的原因,因为它类似于图表数据结构。没有必要将它存放在两个不同的地方。
TreeTables的问题是它们总是需要TreeItems并且不会自动发生。当基础数据发生变化时,常规表格和图表都会自动更新。
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();
}
}