开发者

Repaint thread works fine when triggering business function, but freezes when triggered by reference

开发者 https://www.devze.com 2023-02-18 15:12 出处:网络
It\'s a bit difficult to explain but here is the situation: I\'m programming a Cellular Automation program and have a mainScreen class that extends the JFrame and that JFrame includes the custom Jpan

It's a bit difficult to explain but here is the situation:

I'm programming a Cellular Automation program and have a mainScreen class that extends the JFrame and that JFrame includes the custom Jpanel that is also a thread that continues to repaint his self. The main class (App) creates the mainScreen.

Now is the strange thing that it is working (real-time view of the generations) when i call the business function (that is envolving the cells in a while loop) from the App class, but when i call the same function from th开发者_如何转开发e MainScreen class (through keyboard input) then the repainting doesn't accour, but i see console output that the generations are envolving.. And the program isn't responding to the close cross of the window, and in the other scenario it closes just like normal when running the algorithm.

So, why isn't my Jpanel repainting? Hope you guys (girls) can help.

Class relation: App<-MainScreen<-MapPanel

App

package Business;

import GUI.MainScreen;
import java.util.Random;

public class App {
    public static final int _CELL_SIZE = 5;
    public static final int _WIN_WIDTH = 800;
    public static final int _WIN_HEIGTH = 600;
    public static final int _HELP_HEIGTH = 72;
    public static final double _LIFE_START = 0.1F;

    private MainScreen _mainScreen;
    private Cell[][] _map;
    private int _generation;
    private Random _random;
    private boolean _running;

public App() {
    _generation = 0;
    _running = false;
    _random = new Random(System.currentTimeMillis());
    newMap();
    _mainScreen = new MainScreen(this);
    //envolveCells();
    //cout();
}

public void envolveCells() {
    _generation = 0;
    _running = true;
    Cell[][] newMap = new Cell[getNumOfRows()][getNumOfCells()];

    while(_running) {
        newMap = new Cell[getNumOfRows()][getNumOfCells()];

        //envolve cells
        for(int row = 0; row < getNumOfRows(); row++) {
            for(int cell = 0; cell < getNumOfCells(); cell++) {
                System.out.println(_map[row][cell].envolve());
                newMap[row][cell] = new Cell(_map[row][cell].envolve());
                newMap[row][cell].setNeighbors(_map[row][cell].getNeighbors());
            }
        }

        _map = newMap;
        _generation++;

        try {
            Thread.sleep(100);
        } catch(Exception ex) { }
    }
}

package GUI;

import Business.App; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.JFrame;

public class MainScreen extends JFrame implements KeyListener { private App _app; private MapPanel _mapPanel;

public MainScreen(App app){
    _app = app;
    _mapPanel = new MapPanel(app);

    setTitle("Cellular Automaton sandbox - Sven van Zoelen");
    setSize(App._WIN_WIDTH, App._WIN_HEIGTH + App._HELP_HEIGTH);
    setResizable(false);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    add(_mapPanel);
    addKeyListener(this);

    setVisible(true);
}

public void keyTyped(KeyEvent e) {
    if(e.getKeyChar() == 'r') {
        System.out.println("Run mode");
        _app.envolveCells();
    }
}

MapPanel

package GUI;

import Business.App;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

public class MapPanel extends JPanel implements Runnable {
    private App _app;
    private Font _font = new Font("Arial", Font.PLAIN, 10);

public MapPanel(App app) {
    _font = new Font("Arial", Font.PLAIN, 10);
    _app = app;

    new Thread(this).start();
}
....
public void run() {
    while(true) {
        repaint();

        try {
            Thread.sleep(50);
        } catch(Exception ex) { }
    }
  }
}


Your "business logic" looks like it should run at a separate thread from the GUI. Thus, don't invoke it directly from the GUI thread (in the action listener), but put it in a new Thread there.

As long as your action listener (or key-listener, in this case) does not return, your GUI will not be painted, as painting occurs in the same thread as input-handling.

public void keyTyped(KeyEvent e) {
    if(e.getKeyChar() == 'r') {
        new Thread("envolver") { public void run() {
           System.out.println("Run mode");
           _app.envolveCells();
        }).start();
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号