简体   繁体   中英

Displaying graphics as they paint in swing

I created a maze generator in swing for a class, and it works great. The only thing is, I want to show the maze being created in realtime, but the way I have everything set, it only updates after all the calculations have completed. I am using paintComponent and repaint in my code. How do I have it show the JFrame and draw lines immediately, rather than doing the algorithm and showing them all at the end?

Here is the relevant code:

 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();
    }

Here is my paintComponent method 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);
            }
        }
    }

The knockWalls method sets certain walls equal to null, which causes them to not be drawn in the paintComponent method. I'm still fairly new at a lot of this, so I apologize if some of the code isn't super high quality!

Thanks everyone.

As MadProgrammer already pointed out in the comments, you are almost certainly blocking the Event Dispatch Thread. This is the thread that is responsible for repainting the GUI, and for handling the interaction events (like mouse clicks and button presses).

So presumably, you start the computation via a button click, roughly like this:

// The actionPerformed method of the button that
// starts the maze solving computation
@Override
void actionPerformed(ActionEvent e)
{
    generateMaze();
}

That means that the event dispatch thread will be busy with executing generateMaze() , and not be able to perform the repainting.

The simplest solution would be to change this to something like

// 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();
}

However, some care has to be taken: You may not modify Swing components from this newly created thread. If you have to modify Swing components, you have to put the task that performs the actual modification of the Swing component back on the EDT, using SwingUtilities.invokeLater(task) . Additionally, you have to make sure that there are no other synchronization issues. For example, the lines

if(boxes[y][x].top != null)
    boxes[y][x].top.paint(g);

are still (and have to be!) executed by the event dispatch thread. In this case, you have to make sure that no other thread can set the boxes[y][x].top to null after the EDT has executed the first line and before it executes the second line. If this may be an issue in your case, you might have to provide a bit more code, eg the code that is showing where and how the boxes[y][x] are modified.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM