动态更改JavaFX图表的数据和颜色

时间:2017-06-08 07:23:39

标签: java javafx charts bar-chart

我有一个小程序,它连接数据库以获取数据并在StackedBarChart中显示。在我插入数据之前,我会为每天和客户排序。我也有一个ComboBox,让用户选择一天。 因此每次更改日期时,我都会清除图表数据并添加新数据。然后我想动态更改颜色,因为我不知道将显示多少客户。我知道在演出舞台后我必须这样做。 在程序开始时,第一个图表显示了它们看起来正确。堆叠条和图例的颜色已更改,不会重复。但如果我选择另一天,传奇的颜色不会改变并显示相同的八种颜色,重复的是八个以上的顾客。 这是我的一段代码:

public class BarChartSample extends Application
{
    StackPane chartPane;
    StackPane comboboxPane;
    BorderPane layout;
    Scene scene;
    StackedBarChart<String, Number> bc;
    ComboBox<String> combobox;
    ArrayList<Date> listDates;
    ArrayList<Customer> listCustomers;
    HashMap<String, ArrayList<XYChart.Series<String, Number>>> listData;
    ArrayList<Day> listDays;
    ObservableList<String> xCategories = 
            FXCollections.<String> observableArrayList("6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19");
    StackedBarChart<String, Number> chart;

    @Override
    public void start(Stage stage) throws Exception
    {
        try
        {
                boolean dataExists = getDataSortedByDay();
                if (dataExists)
                {
                    stage.setTitle("Title");
                    ArrayList<String> weekdays = dateToWeekday(listDates);
                    CategoryAxis xAxis = new CategoryAxis();
                    NumberAxis yAxis = new NumberAxis();
                    xAxis.setLabel("Lieferstunde");
                    xAxis.setCategories(xCategories);
                    yAxis.setLabel("Anzahl Dokumente");
                    chart = new StackedBarChart<String, Number>(xAxis, yAxis);
                    chart.setAnimated(false);
                    chart.applyCss();
                    listData = new HashMap<String, ArrayList<XYChart.Series<String, Number>>>();
                    // create for every day a new chart and save to hashmap
                    for (Day day : listDays)
                    {
                        // create for every customer of a day a new series
                        ArrayList<XYChart.Series<String, Number>> listSeries = new ArrayList<XYChart.Series<String, Number>>();
                        for (Customer customer : day.getListCustomers())
                        {
                            XYChart.Series<String, Number> series = new XYChart.Series<String, Number>();
                            series.setName(customer.getName());
                            series.getData().add(new XYChart.Data<String, Number>(String.valueOf(customer.getHour()), customer.getNumDocs()));
                            listSeries.add(series);
                        }
                        listData.put(dateToWeekday(day.getDate()), listSeries);
                    }
                    chartPane = new StackPane();
                    chart.getData().addAll(listData.get(weekdays.get(0)));
                    chartPane.getChildren().add(chart);
                    comboboxPane = new StackPane();
                    comboboxPane.getChildren().add(createComboBoxMenu(weekdays));
                    layout = new BorderPane();
                    layout.setTop(comboboxPane);
                    layout.setCenter(chartPane);
                    scene = new Scene(layout, 1000, 800);
                    stage.setScene(scene);
                    stage.centerOnScreen();
                    stage.show();
                    chart.setTitle(weekdays.get(0));
                    changeColorsOfChart(chart);
                }
                else
                {
                    // no data found
                }
        }
        catch (ClassNotFoundException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   
    }
public ComboBox<String> createComboBoxMenu(ArrayList<String> weekdays)
    {
        ContextMenu contextMenu = new ContextMenu();
        for (String date : weekdays)
        {
            MenuItem menuItem = new MenuItem(date);
            contextMenu.getItems().add(menuItem);
        }
        combobox = new ComboBox<String>(FXCollections.<String> observableArrayList(weekdays));
        combobox.setContextMenu(contextMenu);
        combobox.valueProperty().addListener(new ChangeListener<String>()
        {
            @Override
            public void changed(ObservableValue<? extends String> ov, String oldValue, String newValue)
            {
                chart.getData().clear();
                chart.getData().addAll(listData.get(newValue));
                changeColorsOfChart(chart);
            }
        });
        return combobox;
    }

    public void changeColorsOfChart(StackedBarChart<String, Number> chart)
    {
        ArrayList<Color> listColors = new ArrayList<Color>();
        for (int i = 0; i < chart.getData().size(); i++)
        {
            Set<Node> seriesNodes = chart.lookupAll(".series" + i);
            String rgb = randomColorRgbFormat();
            while (listColors.contains(rgb))
            {
                rgb = randomColorRgbFormat();
            }
            for (Node n : seriesNodes)
            {
                n.setStyle("-fx-background-color: rgb(" + rgb + "); ");
            }
        }
    }

    public String randomColorRgbFormat()
    {
        Color color = new Color(Math.random(), Math.random(), Math.random(), 0);
        return String.format("%d, %d, %d, 1.0", (int) (color.getRed() * 255), (int) (color.getGreen() * 255),
                (int) (color.getBlue() * 255));
    }

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

我已经在stackoverflow和其他网站上查了很多,并找到了jewelseas的例子。但是,当数据总是在变化时,我无法解决问题。 如果您需要更多信息来帮助我,请告诉我们!

1 个答案:

答案 0 :(得分:0)

感谢Sedrick Jefferson。他的链接解决了这个问题。 这是我改变颜色的新代码:

public void changeColorsOfChart(StackedBarChart<String, Number> chart)
    {
        ArrayList<Color> listColors = new ArrayList<Color>();
        HashMap<String, String> colors = new HashMap<String, String>();
        for (XYChart.Series<String, Number> series : chart.getData()) 
        {
            String rgb = randomColorRgbFormat();
            while (listColors.contains(rgb))
            {
                rgb = randomColorRgbFormat();
            }
            for (XYChart.Data<String, Number> data : series.getData())
            {
                data.getNode().setStyle("-fx-bar-fill: rgb(" + rgb + ");");
            }
            colors.put(series.getName(), rgb);
        }
        for (Node n : chart.getChildrenUnmodifiable())
        {
            if (n instanceof Legend)
            {
                for (LegendItem items : ((Legend)n).getItems())
                {
                    String rgb = colors.get(items.getText());
                    items.getSymbol().setStyle("-fx-bar-fill: rgb(" + rgb + ");");
                }
            }
        }
    }