Question

I am writing a genetic algorithm that approximates an image with a polygon. While going through the different generations, I'd like to output the progress to a JFrame. However, it seems like the JFrame waits until the GA's while loop finishes to display something. I don't believe it's a problem like repainting, since it eventually does display everything once the while loop exits. I want to GUI to update dynamically even when the while loop is running.

Here is my code:

while (some conditions) {
    //do some other stuff
    gui.displayPolygon(best);
    gui.displayFitness(fitness);
    gui.setVisible(true);
}

public void displayPolygon(Polygon poly) {
    BufferedImage bpoly = ImageProcessor.createImageFromPoly(poly);
    ImageProcessor.displayImage(bpoly, polyPanel);
    this.setVisible(true);
}

public static void displayImage(BufferedImage bimg, JPanel panel) {
    panel.removeAll();
    panel.setBounds(0, 0, bimg.getWidth(), bimg.getHeight());
    JImagePanel innerPanel = new JImagePanel(bimg, 25, 25);
    panel.add(innerPanel);
    innerPanel.setLocation(25, 25);
    innerPanel.setVisible(true);
    panel.setVisible(true);
}
Was it helpful?

Solution

I think your problem is that Java won't let you update the GUI from another thread than the GUI thread itself. This causes grief to everybody at some point, but fortunately a reasonably convenient workaround is provided.

The idea is to pass the code that does the updating as a Runnable to the method SwingUtilities.invokeAndWait or SwingUtilities.invokeLater. Here's an example.

To run your GA at maximum speed and exploit parallelism, I guess invokeLater would be appropriate.


EDIT: Oh wait, camickr's solution hints that you're doing something else: You're running the GA in the GUI's thread. Well, that can only do one or the other, calculate or display. So the true solution would combine both changes:

  1. Run the GA in a separate thread (you could run it in the thread used by main() after you've instantiated the GUI); and
  2. Use invokeLater to communicate updates to the GUI thread (which camickr calls the EDT, or Event Dispatch Thread).

OTHER TIPS

However, it seems like the JFrame waits until the GA's while loop finishes to display something. I don't believe it's a problem like repainting

Yes, if the looping code execute on the EDT then the GUI can't repaint itself until the loop finishes. The looping code should execute in its own Thread so it doesn't block the EDT.

Read the section from the Swing tutorial on Concurrency for more information.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top