Я создал генератор лабиринта в качелях для класса, и он отлично работает. Единственное, что я хочу показать, что лабиринт создается в реальном времени, но так, как у меня все установлено, оно только обновляется после завершения всех вычислений. Я использую paintComponent и перекрашиваю в свой код. Как мне это показать JFrame и нарисовать линии сразу, вместо того, чтобы делать алгоритм и показывать их все в конце?
Вот соответствующий код:
public void generateMaze() {
Stack<Box> stack = new Stack<>();
int totalCells = Finals.numCol * Finals.numRow, visitedCells = 1;
Box currentCell = boxes[0][0];
Box nextCell;
stack.add(currentCell);
while (visitedCells < totalCells) {
nextCell = checkNeighbors(currentCell.xCoord, currentCell.yCoord);
if (nextCell != null) {
knockWalls(currentCell, nextCell);
stack.add(currentCell);
currentCell = nextCell;
visitedCells++;
} else {
currentCell = stack.pop();
}
}
repaint();
}
Вот мой метод paintComponent override
public void paintComponent(Graphics g) {
for(int x = 0; x < Finals.numRow; x++) {
for(int y = 0; y < Finals.numCol; y++) {
if(boxes[y][x].top != null)
boxes[y][x].top.paint(g);
if(boxes[y][x].bottom != null)
boxes[y][x].bottom.paint(g);
if(boxes[y][x].left != null)
boxes[y][x].left.paint(g);
if(boxes[y][x].right != null)
boxes[y][x].right.paint(g);
}
}
}
Метод knockWalls устанавливает определенные стены равными нулю, что заставляет их не рисоваться в методе paintComponent. Я по-прежнему довольно новичок в этом, поэтому я приношу свои извинения, если какой-то код не является супер высоким качеством!
Всем спасибо.
Как уже отмечал MadProgrammer в комментариях, вы почти наверняка блокируете Thread Dispatch Thread. Это поток, который отвечает за перерисовку графического интерфейса и обработку событий взаимодействия (например, щелчков мышью и нажатия кнопок).
Итак, предположим, вы начинаете вычисление с помощью нажатия кнопки, примерно так:
// The actionPerformed method of the button that
// starts the maze solving computation
@Override
void actionPerformed(ActionEvent e)
{
generateMaze();
}
Это означает, что поток отправки событий будет занят выполнением функции generateMaze()
и не сможет выполнить перерисовку.
Самое простое решение - изменить это на что-то вроде
// The actionPerformed method of the button that
// starts the maze solving computation
@Override
void actionPerformed(ActionEvent e)
{
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
generateMaze();
}
});
thread.start();
}
Однако необходимо позаботиться: вы не можете изменять компоненты Swing из этого вновь созданного потока. Если вам нужно изменить компоненты Swing, вам нужно поставить задачу, которая выполняет фактическую модификацию компонента Swing на EDT, используя SwingUtilities.invokeLater(task)
. Кроме того, вы должны убедиться, что других проблем синхронизации нет. Например, линии
if(boxes[y][x].top != null)
boxes[y][x].top.paint(g);
по-прежнему (и должны быть!) выполнены потоком отправки событий. В этом случае вы должны убедиться, что ни один другой поток не сможет установить boxes[y][x].top
в null
после того, как EDT выполнит первую строку и перед выполнением второй строки. Если это может быть проблемой в вашем случае, возможно, вам придется предоставить немного больше кода, например код, который показывает, где и как изменяются boxes[y][x]
.