0
votes

Some background info: I'm creating a system to register lost, found and returned luggage. The amount of those 3 variable need to be in a LineChart to get a nice overview from how much luggage is lost etc. over an amount of time.

Now the problem: When I create a LineChart and add it to a ChartPanel the LineChart represent a dataset. I've heard that when you edit/update your dataset, the chart is also automatically updated. Well I have an update button next to the chart which has to update the chart when clicked. Independent of the chart in an already existing JPanel/ChartPanel I also create a new frame which represent a ChartFrame.

When I click the update button a new frame pops-up and with the most recent data from the updated dataset. When I click it again, obviously another frame is created, but the already existing frame is also update while the chart in the JPanel isn't though they use the same dataset which is static and comes from a LineChart model.

Well here some code:

LineChartModel

//At the top of the document the dataset is initialize static
public static DefaultCategoryDataset dataset = null;

/*****************Other code omitted***********************/
/**
 * 
 * Updates an already existing dataset
 * 
 * @param dataset
 * @return dataset
 */
public CategoryDataset updateDataset(DefaultCategoryDataset dataset) {

    this.dataset = dataset; 

    // row keys...
    final String rowLost = "Lost";
    final String rowFound = "Found";
    final String rowReturned = "Returned";


    //Don't pay attention to this. It's setting the value for the dataset from different arrays which I know of the are filled correctly
    int i = 0;
    while (i < 12) {

        dataset.setValue(lost[i], rowLost, type[i]);
        System.out.println("There were " + lost[i]
                + " lost luggages in month: " + type[i]);
        i++;
    }
    for (int j = 0; j < 12; j++) {
        dataset.setValue(found[j], rowFound, type[j]);
        System.out.println("There were " + found[j]
                + " found luggages in month: " + type[j]);
    }
    for (int j = 0; j < 12; j++) {
        dataset.setValue(returned[j], rowReturned, type[j]);
        System.out.println("There were " + returned[j]
                + " returned luggages in month: " + type[j]);
    }
    return dataset;

}

The LineChart Class with his constructor

LineChartModel model = new LineChartModel();
public ChartPanel chartPanel;
/**
 * Creates a new demo.
 *
 * @param title  the frame title.
 */
public LineChart(final String title, LineChartModel m) {
    m = model;
    m.selectRange();
    m.createDataset();
    final JFreeChart chart = createChart(m.dataset);
    chartPanel = new ChartPanel(chart);
    chartPanel.setPreferredSize(new Dimension(500, 270));
}

ChartController

First the params of the constructor

public ChartController(final ManCharts v, final LineChartModel m) {
    view = v;
    model = m;

And here the actionlistener of the button.

    //Select a range by sumbitting the variables
    v.date.btnSubmit.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            //selectRange select all the data between 2 dates but isn't important for this problem
            m.selectRange(/*v.date.dateChooserFrom, v.date.dateChooserTo*/);

            //updateDataset updates the dataset from the LineChartModel which is static
            m.updateDataset(m.dataset);

            //The data in the chart should already be updated but here I'm trying to replace the current chart by a new one
            v.chart.chartPanel = new ChartPanel(v.chart.createChart(m.dataset));

            //This is the new chart which does automatically update when the button is pressed
            JFreeChart chart = ChartFactory.createLineChart("Something chart", "Date", "Value", m.dataset);
            ChartFrame frame = new ChartFrame("New line chart", chart);
            frame.setVisible(true);
        }
    });

I really hope someone can help and that this problem is not too complicated without having the full code.

If you need more code or something. Just say so.

Thanks in advance!

EDIT! I think it has to do something with how I create the chart. The chart in my JPanel which is created at the start of my application is created with an edited method (this is part of my LineChart class and stands below my constructor):

/**
 * Creates a sample chart.
 * 
 * @param dataset  a dataset.
 * 
 * @return The chart.
 */
public JFreeChart createChart(final CategoryDataset dataset) {

    // create the chart...
    final JFreeChart chart = ChartFactory.createLineChart(
        "Luggage",       // chart title
        "Time",                    // domain axis label
        "Value",                   // range axis label
        dataset,                   // data
        PlotOrientation.VERTICAL,  // orientation
        true,                      // include legend
        true,                      // tooltips
        false                      // urls
    );



    chart.setBackgroundPaint(Color.decode("#d6d9df"));

    final CategoryPlot plot = (CategoryPlot) chart.getPlot();
    plot.setBackgroundPaint(Color.lightGray);
    plot.setRangeGridlinePaint(Color.white);

    // customise the range axis...
    final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
    rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
    rangeAxis.setAutoRangeIncludesZero(true);


    // customise the renderer...
    final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
    //renderer.setDrawShapes(true);

    renderer.setSeriesStroke(
        0, new BasicStroke(
            2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
            1.0f, new float[] {10.0f, 6.0f}, 0.0f
        )
    );
    renderer.setSeriesStroke(
        1, new BasicStroke(
            2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
            1.0f, new float[] {6.0f, 6.0f}, 0.0f
        )
    );
    renderer.setSeriesStroke(
        2, new BasicStroke(
            2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
            1.0f, new float[] {2.0f, 6.0f}, 0.0f
        )
    );
    // OPTIONAL CUSTOMISATION COMPLETED.

    return chart;
}

SOLVED It had to do with another dataset that was created when clicking the submit button. So I've fixed the recreation and it's working now. Not really a chart problem, but just a problem in my model. Thanks for the help anyway!

1

1 Answers

1
votes

ChartPanel implements an event listener that prompts it to repaint() itself when needed; JPanel does not. See the implementation of ChartChangeListener in chartChanged(), for example. When debugging, look for one instance of ChartPanel that shadows another or an errant use of JPanel.

Addednum Does the frame also need to be an ApplicationFrame or could it work in a JFrame?

Either is acceptable, as shown in this JFrame example or this ApplicationFrame example; both update dynamically. Note that Swing GUI objects should be constructed and manipulated only on the event dispatch thread.