繁体   English   中英

在挥杆绘画时显示图形

[英]Displaying graphics as they paint in swing

我为一个班级创建了一个迷宫生成器,效果很好。 唯一的事情是,我想实时显示正在创建的迷宫,但是我已经设置了所有方法,它仅在所有计算完成后才更新。 我在代码中使用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方法重写

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

kickWalls方法将某些墙设置为null,这使得它们不会在paintComponent方法中绘制。 我在这方面还算是新手,因此,如果某些代码质量不是很高,我深表歉意!

感谢大家。

正如MadProgrammer在评论中已经指出的那样,几乎可以肯定的是,您将阻止Event Dispatch Thread。 这是负责重新绘制GUI 以及处理交互事件(例如鼠标单击和按钮按下)的线程。

因此,大概是通过单击按钮开始计算,大致如下所示:

// 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组件,则必须使用SwingUtilities.invokeLater(task)将执行实际修改Swing组件的任务放回EDT。 此外,您必须确保没有其他同步问题。 例如,线

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

仍然(必须!)由事件分发线程执行。 在这种情况下,必须确保在EDT执行第一行之后并且在执行第二行之前,没有其他线程可以将boxes[y][x].topnull 如果这可能是您的问题,则可能需要提供更多代码,例如,显示在哪里以及如何修改boxes[y][x]的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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