在SwingWorker中渲染游戏地图的Java无法正常工作

时间:2012-11-05 18:02:45

标签: java multithreading user-interface rendering swingworker

我目前正在开发一款游戏,需要在JPanel(或其他容器)上绘制类似网格的地图。 为了在合理的时间内实现这一点,并保持我的UI响应,我传递容器的图形对象 到地图渲染器,它是SwingWorker的子类。然后我调用地图渲染器的execute方法,它开始实际绘制地图。绘图完成后,将打印一条消息。当我按下M键时,所有这一切都开始了。

实际问题是第一次绘制地图是成功的。当我反复按M键时,我从未收到任何其他完成的消息。此外,当我ALT-TAB退出我的应用程序(以全屏独占模式运行)并重新进入时,我的地图不再可见。

我怀疑这个问题不是直接在EDT线程中绘图,或者没有正确传递我的地图渲染器已准备就绪。

这是我的地图渲染器类:

    public class MapRenderer extends SwingWorker<Void, Void> {

private Graphics2D g;
private WorldMap map;
private int x, y, w, h, l;


@Override
protected Void doInBackground() throws Exception {
    drawMap();
    return null;
}

@Override
protected void done() {
    super.done();
    System.out.println("Done");
}

private void drawMap() {
    int rw = w + 1;
    int rh = h + 1;

    if (rw >= map.getSize())
        rw = map.getSize();
    if (rh >= map.getSize())
        rh = map.getSize();

    for (int i = 0; i < rw; i++) {
        for (int j = 0; j < rh; j++) {
            g.setColor(map.getTiles()[x + i][y + j].getColor());
            g.fillRect(i * l, j * l, l, l);
            if (l > 2) {
                g.setColor(Color.DARK_GRAY);
                g.drawRect(i * l, j * l, l, l); 
            }
        }
    }
}

public void setGraphics(Graphics2D g) {
    this.g = g;
}

public void setMap(WorldMap map) {
    this.map = map;
}

public void setViewPoint(Rectangle viewPoint, int squareSize) {
    this.x = (int) viewPoint.getX();
    this.y = (int) viewPoint.getY();
    this.w = (int) viewPoint.getWidth();
    this.h = (int) viewPoint.getHeight();
    this.l = squareSize;
}
    }

这是调用execute()方法的地方:

private void initializeKeyBindings() { 
    this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("M"), "M");
    this.getActionMap().put("M", new AbstractAction() {
        private static final long serialVersionUID = 1L;
        @Override
        public void actionPerformed(ActionEvent e) {
            drawMap(getGraphics());
        }
    });
}

public void drawMap(Graphics g) {
    mapRenderer.setGraphics((Graphics2D) g);
    mapRenderer.setViewPoint(new Rectangle(0, 0, 1600 / 4, 900 / 4), 4);
    mapRenderer.execute();
}

我为任何草率的编码道歉,我保证将来会清理它。

1 个答案:

答案 0 :(得分:1)

实现SwingWorker的类的一个实例只能运行一次。因此,每次执行代码时都应该创建一个新实例。从您提供的代码中,您看起来好像在使用相同的实例。因此,它将第一次工作,但不会连续调用:

public void drawMap(Graphics g) {
    mapRenderer.setGraphics((Graphics2D) g);
    mapRenderer.setViewPoint(new Rectangle(0, 0, 1600 / 4, 900 / 4), 4);
    mapRenderer.execute();
}