我正在从事计算机科学项目,并且在接近72小时后一直被这个问题困扰。我第三次使用谷歌,谷歌和谷歌。不知何故,我似乎无法让它发挥作用。基本上,我必须画一个迷宫,然后为解决方案路径设置动画。这是我到目前为止的绘画代码,绘制迷宫的作品很好,我根本无法让它生动。
private class MazePanel extends JPanel
{
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
MazeApp.g = (Graphics2D) g;
paintMaze();
}
}
...
private static Timer timer = new Timer(1000, new ActionListener(){
private int space = 0;
@Override
public void actionPerformed(ActionEvent e)
{
Point3d p = solutionSpaces.get(space);
g.fillRect((int)p.x * spaceLength, (int)p.y * spaceWidth, spaceLength, spaceWidth); // g is static reference to Graphics2D, set from MazePanel
mazePanel.repaint(); //mazePanel is instance
space++;
}
});
...
private void paintMaze()
{
if (this.reader != null)
{
for (int col = 0; col < this.reader.getWidth(); col++)
{
for (int row = 0; row < this.reader.getLength(); row++)
{
MazeConstruct c = reader.check(row, col, floor);
if (c == MazeConstruct.WALL)
g.setColor(Color.BLACK);
else if (c == MazeConstruct.ELEVATOR)
g.setColor(Color.YELLOW);
else if (c == MazeConstruct.START)
g.setColor(Color.CYAN);
else if (c == MazeConstruct.FINISH)
g.setColor(Color.RED);
else if (c == MazeConstruct.OPEN)
g.setColor(Color.GRAY);
if (c != MazeConstruct.SOLUTION && c != MazeConstruct.TRAVERSED)
g.fillRect(row * spaceLength, col * spaceWidth, spaceLength, spaceWidth);
g.setColor(Color.DARK_GRAY);
g.drawRect(row * spaceLength, col * spaceWidth, spaceLength, spaceWidth);
}
}
}
if (solving)
{
timer.setInitialDelay(0);
timer.start();
}
}
提供的代码将立即充分绘制完整的解决方案,但我需要它作为动画逐步浏览每个单独的空间。请帮我。这是我绝对的最后手段!如果我需要提供任何其他信息,请告诉我。此外,欢迎建设性的批评。非常感谢。
[编辑]我在这里发现了一个随机问题,其中提出了一个通用点,即计时器的刻度(actionPerformed())应该只更新数据的状态(例如移动到下一个空格)而不是实际绘制,并且那个图形在paintComponent调用之后不应该保持g。我将使用这些新的小信息来解决我的问题。答案仍然受到欢迎。
答案 0 :(得分:0)
如果我理解你的问题(如果没有,请纠正我),当你逐步浏览每个空间时,你不能让屏幕更新。在这种情况下你会使用repaint();方法
答案 1 :(得分:0)
在渲染图形Component
时,您必须记住几件事:
1)Graphics
和Graphics2D
对象不是永久性的,它是在调用repaint()时临时创建的,你不能依赖Graphics
对象的副本(比如保存它)作为静态变量)。使用后必须将其丢弃。
2)仅使用传递给paintComponent()方法的Graphics
对象的副本,从paintComponent()
方法内部使用Graphics
对象调用所有方法。
以下是您必须使用的模板:
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.draw...(...);
g.fill...(...);
yourMethod((Graphics2D)g);
....
....
}
private void yourMethod(Graphics2D g) {
g.setPaint(..);
g.draw...();
....
}
您正在保存Graphics对象并在paintComponent()之外使用它不正确,并可能导致未定义的行为。您使用已保存的g.fillRect((int)p.x * spaceLength, (int)p.y * spaceWidth, spaceLength, spaceWidth);
!实例调用g
,这是一个严重的问题。
另一件需要记住的事情是,如果drawaint()方法已被绘制,则它可能不会调用paintComponent()。
以上模板适用于您的情况。但是,如果你真的对非常好的表现感兴趣(完成大量的绘图),你必须使用双缓冲(即使用单独的线程绘制到图像然后立即将图像放在屏幕上)。