2

I have a JavaFX app that utilizes the lineChart chart. I can write a chart to the app, and clear it, but when I want to write a new series and have it displayed, I get an error,

java.lang.IllegalArgumentException: Children: duplicate children added: 

I understand the meaning, but not how to fix (I am very new to Java, let alone to FX).

Here is the relevant code from my controller (minus some class declarations):

(method called by the 'submit' button in chart tab window)

@FXML
private void getEngDataPlot(ActionEvent event)  {


 //check time inputs
   boolean start = FieldVerifier.isValidUtcString(startRange.getText());
   boolean end = FieldVerifier.isValidUtcString(endRange.getText());
   type = engData.getValue().toString();

 // Highlight errors.
   startRangeMsg.setTextFill(Color.web(start ? "#000000" : "#ff0000"));
   endRangeMsg.setTextFill(Color.web(end ? "#000000" : "#ff0000"));

    if (!start || !end ) {
        return;
    }

    // Save the preferences.
    Preferences prefs = Preferences.userRoot().node(this.getClass().getName());
    prefs.put("startRange", startRange.getText());
    prefs.put("endRange", endRange.getText());
    prefs.put("engData", engData.getValue().toString());

    StringBuilder queryString = new StringBuilder();
    queryString.append(String.format("edit out",
            startRange.getText(),
            endRange.getText()));
        queryString.append(type);

    log(queryString.toString());

    // Start the query task.
    submitEngData.setDisable(true);
    // remove the old series.
    engChart.getData().clear();
    engDataProgressBar.setDisable(false);
    engDataProgressBar.setProgress(-1.0);
    //ProgressMessage.setText("Working...");
    Thread t = new Thread(new EngDataPlotTask(queryString.toString()));
    t.setDaemon(true);
    t.start();

}

(the task called by above method:)

public EngDataPlotTask(String query) {
    this.query = query;
    }

    @Override
    protected Void call() {
  try {
           URL url = new URL(query);
           String inputLine = null; 

           BufferedReader in = new BufferedReader(
           new InputStreamReader(url.openStream()));
       //    while ( in.readLine() != null){
                inputLine = in.readLine();  //}

             Gson gson = new GsonBuilder().create();  
             DataObject[] dbin = gson.fromJson(inputLine, DataObject[].class);
              in.close();

           for (DataObject doa : dbin)  {         
              series.getData().add(new XYChart.Data(doa.danTime, doa.Fvalue));    

           }

           xAxis.setLabel("Dan Time (msec)");

      } catch (Exception ex) {
            log(ex.getLocalizedMessage());
      }

           Platform.runLater(new Runnable() {
            @Override
            public void run() {
                submitEngData.setDisable(false);
                // do some pretty stuff
                String typeName = typeNameToTitle.get(type);

                series.setName(typeName); 
               // put this series on the chart
                engChart.getData().add(series);

                engDataProgressBar.setDisable(true);
                engDataProgressBar.setProgress(1.0);
              }
        });  

    return null;
    }
} 

The chart draws a first time, clears, and then the exception occurs. Requested stack trace follows:

Exception in runnable

java.lang.IllegalArgumentException: Children: duplicate children added: parent = Group@8922394[styleClass=plot-content] at javafx.scene.Parent$1.onProposedChange(Unknown Source) at com.sun.javafx.collections.VetoableObservableList.add(Unknown Source) at com.sun.javafx.collections.ObservableListWrapper.add(Unknown Source) at javafx.scene.chart.LineChart.seriesAdded(Unknown Source) at javafx.scene.chart.XYChart$2.onChanged(Unknown Source) at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(Unknown Source) at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(Unknown Source) at com.sun.javafx.collections.ObservableListWrapper.callObservers(Unknown Source) at com.sun.javafx.collections.ObservableListWrapper.add(Unknown Source) at com.sun.javafx.collections.ObservableListWrapper.add(Unknown Source) at edu.arizona.lpl.dan.DanQueryToolFX.QueryToolController$EngDataPlotTask$1.run(QueryToolController.java:231) at com.sun.javafx.application.PlatformImpl$4.run(Unknown Source) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.access$100(Unknown Source) at com.sun.glass.ui.win.WinApplication$2$1.run(Unknown Source) at java.lang.Thread.run(Thread.java:722)

Any ideas what I am doing wrong. I am a RANK NEWBIE, so please take that into account if you wish to reply. Thank you!

passiflora
  • 125
  • 5
  • 13
  • Please update the question to include the full stack trace to the exception if you have it. – jewelsea Aug 16 '12 at 00:35
  • Refer to the answer if still facing this issue.

    [https://stackoverflow.com/a/46234511/4821500](https://stackoverflow.com/a/46234511/4821500)
    – Anurag Upadhyaya Sep 15 '17 at 08:00

3 Answers3

4

It took long time to find a workaround solution for this issue.

Please add below piece of code and test:

engChart.getData().retainAll();
engChart.getData().add(series);
Jake1164
  • 12,291
  • 6
  • 47
  • 64
Murali
  • 41
  • 1
0

My guess about the root cause according to your incomplete code is this line:

engChart.getData().add(series);

You should add series only once in initialize block for instance. But I think in your task thread, you are adding the already added same series again and having that mentioned exception. If your aim is to refresh the only series data, then just manipulate the series, getting it by engChart.getData().get(0); and delete that line in the code.

Uluk Biy
  • 48,655
  • 13
  • 146
  • 153
  • Uluk - Ok. Fine. But when I remove that line of code, the graph does not refresh. I can clear the series, I can manipulate the series, but that line you cite is where the series gets drawn on the chart, near as I can tell. So I do not see in the other methods an obvious way to redraw an updated series, once created, on the existing chart. – passiflora Aug 16 '12 at 17:27
0

Once you add the series to the graph all you do is edit the series. Don't add it to the graph again. The graph will follow whatever happens to the series i.e. just change the series data and the graph will automatically reflect the changes.