Como faço para exibir as atualizações do JPanel durante o loop?

Estou em um dilema, e já tentei diversas maneiras para conseguir isso, inclusive métodos como repaint(), validate() e revalidate(), porém sem sucesso.

package telas;

import com.sun.webkit.ContextMenu;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import principal.Busca;
import principal.Estado;
import principal.Matriz;
import principal.Posicao;

public class Tela extends JFrame {

private JPanel panel;
private Matriz<JButton> matrizes;

private Stack<Estado> pilha = new Stack<>();

private Lab labirinto;
private Agente personagem;

public Tela(Busca busca) {
    //Tamanho do Jframe
    this.setSize(500, 500);
    //A tela não pode ser maximizada nem minimizada
    this.setResizable(false);

    //Centraliza a tela
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    iniciar(busca);
}

public void iniciar(Busca busca) {
    Posicao itemAtual;

    ImageIcon icon = new ImageIcon("/home/bruno/NetBeansProjects/TP - IA/Agente_P.png", "Agente");
    icon.setImage(icon.getImage().getScaledInstance(35, 35, 100));

    this.pilha.addAll(busca.getCaminho());
    Collections.reverse(pilha);

    this.setLayout(new BorderLayout());
    //Matriz de botões vai ser utilizada para preencher a tela 
    this.matrizes = new Matriz<>(busca.getMatriz().getLinhas(), busca.getMatriz().getColunas());

    //O GridLayout tem a funcionalidade de organizar a matriz, dado as linhas e colunas
    panel = new JPanel(new GridLayout(busca.getMatriz().getLinhas(), busca.getMatriz().getColunas()));

    while (!pilha.isEmpty()) {
        try {
            itemAtual = pilha.pop().getAgente();
            for (int i = 0; i < busca.getMatriz().getLinhas(); i++) {
                for (int j = 0; j < busca.getMatriz().getColunas(); j++) {

                    matrizes.adiciona(i, j, new JButton(""));
                    matrizes.retornaValor(i, j).setSize(i, j);

                    if (itemAtual.getX() == i && itemAtual.getY() == j) {
                        matrizes.retornaValor(i, j).setIcon(icon);
                        matrizes.retornaValor(i, j).setBackground(Color.RED);
                    } else {
                        if ((int) busca.getMatriz().retornaValor(i, j) == 0) {
                            //  matrizes.retornaValor(i, j).setBackground(new Color(0f, 0f, 0f, 0f));
                            matrizes.retornaValor(i, j).setBackground(Color.BLACK);
                        } else if ((int) busca.getMatriz().retornaValor(i, j) == 1) {
                            matrizes.retornaValor(i, j).setBackground(Color.WHITE);
                        }
                    }
                    panel.add(matrizes.retornaValor(i, j));
                }
            }
            matrizes.retornaValor(busca.getInicio().getX(), busca.getInicio().getY()).setBackground(Color.GREEN);
            matrizes.retornaValor(busca.getFim().getX(), busca.getFim().getY()).setBackground(Color.BLUE);

            //É adicionado o painel no JFrame (Classe extende JFrame)
            getContentPane().add(panel, BorderLayout.CENTER);
            //Seta Jframe para ser exibida
            pack();
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    panel.repaint();
                    panel.revalidate();
                    setVisible(true);
                }
            });

            //JOptionPane.showMessageDialog(panel, "");

            //pausa um determinado tempo o painel
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(Tela.class.getName()).log(Level.SEVERE, null, ex);
        }

        if (!pilha.empty()) {
            //Remove removido tudo que foi adicionado no painel, isso quer dizer que a
            //matrizBotoes foi removida
            panel.removeAll();
        } else {
            JOptionPane.showMessageDialog(rootPane, "Objetivo concluido");
        }
    }
}

}

package telas;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import principal.Busca;
import principal.Matriz;

public class Lab extends JPanel {

/**
 * Creates new form Lab
 */
public Lab() {
    initComponents();
}

private Matriz<JButton> matrizes;

@Override
public void paintComponents(Graphics g) {
    super.paintComponent(g);
}

public Matriz<JButton> getMatrizes() {
    return matrizes;
}

public void setMatrizes(Matriz<JButton> matrizes) {
    this.matrizes = matrizes;
}

public void desenhar(Busca busca) {
    this.matrizes = new Matriz<>(busca.getMatriz().getLinhas(), busca.getMatriz().getColunas());
    for (int i = 0; i < busca.getMatriz().getLinhas(); i++) {
        for (int j = 0; j < busca.getMatriz().getColunas(); j++) {

            this.matrizes.adiciona(i, j, new JButton(""));
            this.matrizes.retornaValor(i, j).setSize(i, j);

            //  É necessário deixar opaco a Jlabel para que seja aplicado cor de fundo
            //    matrizes.retornaValor(i, j).setOpaque(true);
            if ((int) busca.getMatriz().retornaValor(i, j) == 0) {
                //  matrizes.retornaValor(i, j).setBackground(new Color(0f, 0f, 0f, 0f));
                this.matrizes.retornaValor(i, j).setBackground(Color.BLACK);
            } else if ((int) busca.getMatriz().retornaValor(i, j) == 1) {
                this.matrizes.retornaValor(i, j).setBackground(Color.WHITE);
            }

            this.matrizes.retornaValor(i, j).setLayout(new java.awt.GridLayout());
            this.add(this.matrizes.retornaValor(i, j));
            this.matrizes.retornaValor(i, j).setVisible(true);
            this.setLayout(new GridLayout(busca.getMatriz().getLinhas(), busca.getMatriz().getColunas()));
        }
    }

    //  Marcar pontos
    matrizes.retornaValor(busca.getInicio().getX(), busca.getInicio().getY()).setBackground(Color.GREEN);
    matrizes.retornaValor(busca.getFim().getX(), busca.getFim().getY()).setBackground(Color.BLUE);

    // ---------------------------------------------------------------------------------------------------------------------
}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    addContainerListener(new java.awt.event.ContainerAdapter() {
        public void componentAdded(java.awt.event.ContainerEvent evt) {
            formComponentAdded(evt);
        }
    });

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
    this.setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 400, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 300, Short.MAX_VALUE)
    );
}// </editor-fold>                        

private void formComponentAdded(java.awt.event.ContainerEvent evt) {                                    
    // TODO add your handling code here:
}                                   


// Variables declaration - do not modify                     
// End of variables declaration                   

}