1

I am making use of the JFreeChart library to plot the progress of a genetic algorithm in real time.

I'm using Swing for the UI. I have a panel where I draw all the various parameters for the algorithm, and a ChartPanel object. This object is drawn before I call the algorithm's search method (which updates the chart's XYSeries object at each generation), and at the end of the search, with all the values being accurately plotted.

According to the docs, the ChartPanel object is redrawn when its respective chart is updated. Obviously, the Swing panel itself isn't being redrawn until after the search is done, and I call repaint(), but what can I do to fix this?

This is the chart code:

public class XYSeriesDemo {
    private static final long serialVersionUID = 1L;
    private XYSeries series;
    private JFreeChart chart;

    public XYSeriesDemo(String str) {
        series = new XYSeries(str);
        XYSeriesCollection data = new XYSeriesCollection(series);
        chart = createChart(data);
    }

    public XYSeries getSeries() {
        return series;
    }

    public ChartPanel getChartPanel() {
        return new ChartPanel(chart);
    }

    private JFreeChart createChart(final XYDataset data) {
        JFreeChart chart = ChartFactory.createXYLineChart(
            "Best fitness across generations", 
            "Generation", 
            "Fitness",
            data, 
            PlotOrientation.VERTICAL,
            true, 
            true, 
            false
        );

        XYPlot plot = chart.getXYPlot();
        ValueAxis axis = plot.getDomainAxis();
        axis.setAutoRange(true);
        axis = plot.getRangeAxis();
        axis.setAutoRange(true);
        return chart;
    }
}

In my panel constructor, I'm doing the following (this gets an empty chart drawn):

demo = new XYSeriesDemo("Best fitness");
this.add(demo.getChartPanel());

This is the method that the Swing frame calls in my JPanel object when the user orders a search:

public void solve() {
    gen = new Random(seed);
    XYSeries s = demo.getSeries();
    GeneticAlgorithm ga = new GeneticAlgorithm(pop, crossoverP, mutationP, 
                        eliteSize, maxGens, gen, s);
    best = ga.search();
    state = State.SOLVED;
    time = ga.getTime() / 1E9;

}

At each generation, the search method in the algorithm simply does:

series.add(generation, pop.getBestFitness());

Thank you for reading.

4

3 回答 3

1

I think you call your search process in EDT because of that it can't repaint components.

For updating your panel from code try to use SwingWorker, it can update UI and continue background process. You can find a lot of examples of using in Internet.

Or you can try to use Executors for background search process and updating UI.

于 2013-10-30T11:41:10.640 回答
1

Make sure that you are updating the dataset or series for the chart, ideally directly. The chart should refresh itself.

I would recommend buying the JFreeChart developer guide as it includes all sorts of examples including dynamic charts. The cost of the developer guide is what supports JFreeChart development.

于 2013-10-30T11:33:49.800 回答
0

I think this will work for you

JFreeChart jf = // Your JFreeChart chart Object.
ChartPanel chartPanel = new ChartPanel(jf);
myPanel.add(chartPanel);
myPanel.repaint();
myPanel.revalidate();
于 2013-10-30T12:08:57.320 回答