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);
}
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
Runnableto the methodSwingUtilities.invokeAndWaitorSwingUtilities.invokeLater. Here’s an example.To run your GA at maximum speed and exploit parallelism, I guess
invokeLaterwould 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:
main()after you’ve instantiated the GUI); andinvokeLaterto communicate updates to the GUI thread (which camickr calls the EDT, or Event Dispatch Thread).