在paintComponent(Java)期间阻止更新

时间:2016-07-19 17:54:05

标签: java swing synchronization locking paintcomponent

我遇到的问题是我的onFrame方法在paintComponent期间修改了对象的位置。因为我的JPanel渲染相对于其focus对象位置的场景,所以在绘画期间焦点位置的任何移动都会导致场景的一部分从场景的其余部分转换(这对于玩家来说是可见的屏幕上有白色条纹)。因此,我希望阻止在focus的部分内修改paintComponent

这里的涂料成分:

@Override
public void paintComponent(Graphics g) {

    if (focus == null) {
        return;
    }

    super.paintComponent(g);
    synchronized (focus) {
        universe.getCurrentWorld().render(this, g, true); //draws scene around focus
    }
    focus.getInventory().render(this, g);
    focus.renderHealthBar(g);

    if (dialogQ.peek() != null) {
        dialogQ.peek().render(this, g);
    }

}

调用render方法:

public void render(FocusedWindow g, Graphics gr, boolean showOutlands) {

    level.renderMap(g, gr, showOutlands);
    col.renderAround(g, gr);

    for (Detector p : colliders.toArray(new Detector[0])) {
        p.renderAround(g, gr);
    }

}

实际使用focus的水平渲染方法:

public void renderMap(FocusedWindow g, Graphics gr, boolean renderOutside) {
    int cushion = 4;
    int scaleFactor = 2;
    int minX = g.getFocus().getPos().getX() / Tile.WIDTH - g.getDimensions().getX() / Tile.WIDTH / scaleFactor - cushion;
    int maxX = g.getFocus().getPos().getX() / Tile.WIDTH + g.getDimensions().getX() / Tile.WIDTH / scaleFactor + cushion;
    int minY = g.getFocus().getPos().getY() / Tile.WIDTH - g.getDimensions().getY() / Tile.WIDTH / scaleFactor - cushion;
    int maxY = g.getFocus().getPos().getY() / Tile.WIDTH + g.getDimensions().getX() / Tile.WIDTH / scaleFactor + cushion;

    for (int i = minX; i < maxX; i++) {
        for (int j = minY; j < maxY; j++) {
            if (i >= 0 && i < map.length) {
                if (j >= 0 && j < map[i].length) {
                    map[i][j].drawTile(g, gr, new Vector(i,j));
                }
                else if (renderOutside) {
                    map[0][0].drawTile(g, gr, new Vector(i,j));
                }
            }
            else if (renderOutside) {
                map[0][0].drawTile(g, gr, new Vector(i,j));
            }
        }
    }

}

1 个答案:

答案 0 :(得分:0)

啊,我还需要同步更新世界的onFrame中的代码。添加两个同步块后,它可以正常工作:

@Override
protected void onFrame() {

    long time = getTimestamp();
    double deltaTime = (time - lastTime) / 1000000000d;
    lastTime = time;

    if (deltaTime > 0.2) { //this is shitty
        Main.log("high delta time detected (" + deltaTime + " sec)");
    }

    if (dialogQ != null && dialogQ.peek() != null && dialogQ.peek().update(deltaTime)) {
        dialogQ.poll();
    }

    if (isPaused() || isEditingInventory()) {
        return;
    }

    if (!hasDied && focus != null && focus.isDead()) {
        hasDied = true;
        Main.setOverlay(new DeathOverlay());
    }

    if (universe == null || universe.getCurrentWorld() == null) {
        return;
    }

    repaint();
    synchronized (this) {
        universe.getCurrentWorld().update(deltaTime);
    }

}

@Override
public void paintComponent(Graphics g){

    if (focus == null) {
        return;
    }

    super.paintComponent(g);
    synchronized (this) {
        universe.getCurrentWorld().render(this, g, true);
    }
    focus.getInventory().render(this, g);
    focus.renderHealthBar(g);

    if (dialogQ.peek() != null) {
        dialogQ.peek().render(this, g);
    }

}