JavaFX Table依赖于索引列

时间:2014-06-28 13:16:23

标签: java javafx

我只是一个不高兴的程序员,但我一直在尝试使用JavaFX,并一直在玩演示制作我自己的应用程序。 不确定最好的解决方法但是我正在使用JavaFX制作一个自动堆叠条形图制作工具,它依赖于这样的格式的数据:

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

可以添加客户端,当我添加新标题时,它必须适用于所有客户端

http://i1101.photobucket.com/albums/g435/izzypod5/chart_zps7da8c9df.png
 没有足够的代表发布img

我一直在寻找方法,例如:

  1. 可能有一个动态表,它将列添加到客户端,这将是条形图的x轴标题。
  2. 拥有客户的列表视图,并使其对应于其旁边带有值的标题的表格视图
  3. 在客户名称

    之后添加到客户端的某种数据映射
        public void setClientData(ObservableList<Client> clients) {
        ArrayList<XYChart.Series> seriesList = new ArrayList<XYChart.Series>();
            for (Client client : clients){
               XYChart.Series<String, Integer> series = new XYChart.Series();
               series.setName(client.getName());
               seriesList.add(series);
            }
            for(Series series :seriesList){
                for( int i = 0; i <= twc.length - 1; i++){
                    series.getData().add(new XYChart.Data<String, Number>(twc[i], 1000));
                }
                barChart.getData().add(series);
            }   
    
  4. 因此,当您看到我获取客户端值并使系列迭代循环并为每个设置名称时,我将把标题放在twc字符串数组所在的位置,并且值对应于默认的1000值。

    你可以假设我有一个客户和标题的列表/表格,可以动态添加,但每个客户的标题都是固定的但是每个客户的标题值都是我试图获得的。

    关于如何处理这个问题的最佳方法的任何想法将不胜感激:)

1 个答案:

答案 0 :(得分:0)

我会实现Client这样的事情:

import java.util.HashMap;
import java.util.Map;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

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 ;
    }
}

Title可能非常简单,您甚至可以使用StringProperty

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Title {
    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 ;
    }

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

现在,您可以创建可观察的客户端和标题列表,并在其中注册侦听器,以便在列表中添加或删除项目时更新StackedBarChart的数据。如果您使用的是Java 8,则更简洁的方法是使用EasyBind框架,并将系列和数据的内容绑定到列表中数据的映射。

此示例使用EasyBind

import java.util.Random;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import org.fxmisc.easybind.EasyBind;

public class StackedBarChartExample extends Application {

    private final ObservableList<Title> titles = FXCollections.observableArrayList();
    private final ObservableList<Client> clients = FXCollections.observableArrayList();
    private final ObservableList<Series<String, Number>> mappedSeries = EasyBind.map(
        clients, client -> {
            Series<String, Number> series = new Series<>();
            ObservableList<Data<String, Number>> mappedData = EasyBind.map(
                titles,
                title -> {
                    Data<String, Number> data = new Data<>();
                    data.XValueProperty().bind(title.nameProperty());
                    data.YValueProperty().bind(client.valueProperty(title));
                    return data;
                });
            series.setData(mappedData);
            series.nameProperty().bind(client.nameProperty());
            return series;
        });



    @Override
    public void start(Stage primaryStage) {

        NumberAxis yAxis = new NumberAxis();
        CategoryAxis xAxis = new CategoryAxis();
        xAxis.setAutoRanging(false);
        StackedBarChart<String, Number> barChart = new StackedBarChart<>(xAxis,
                yAxis);
        barChart.setAnimated(false);

        Bindings.bindContent(barChart.getData(), mappedSeries);

        xAxis.setCategories(EasyBind.map(titles, Title::getName));

        Title awaitingResponse = new Title("Awaiting Response");
        Title agreed = new Title("Agreed");
        Title workInProgress = new Title("Work in progress");
        titles.addAll(awaitingResponse, agreed, workInProgress);

        for (int i = 1; i <= 5; i++) {
            Client client = new Client("Test " + i);
            client.setValue(awaitingResponse, i * 1000);
            client.setValue(agreed, 3000);
            client.setValue(workInProgress, (6 - i) * 1000);
            clients.add(client);
        }

        VBox controls = new VBox(5);
        final Random rng = new Random();
        Button newClientButton = new Button("Add client");
        newClientButton.setOnAction(event -> {
            Client client = new Client("Test " + (clients.size() + 1));
            for (Title title : titles) {
                client.setValue(title, rng.nextInt(5000));
            }
            clients.add(client);
        });

        HBox titleControls = new HBox(5);
        titleControls.setAlignment(Pos.CENTER);
        TextField newTitleText = new TextField();
        Button newTitleButton = new Button("Add title");
        newTitleButton.setOnAction(event -> {
            Title title = new Title(newTitleText.getText());
            for (Client client : clients) {
                client.setValue(title, rng.nextInt(5000));
            }
            titles.add(title);
        });
        titleControls.getChildren().addAll(newTitleText, newTitleButton);

        controls.setPadding(new Insets(5));
        controls.setAlignment(Pos.CENTER);
        controls.getChildren().addAll(titleControls, newClientButton);

        BorderPane root = new BorderPane();
        root.setCenter(barChart);
        root.setBottom(controls);
        Scene scene = new Scene(root, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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