Графика Java мигает

хорошо, я понимаю вашу потребность в SSCCE, поэтому я создал (мой первый).

мне удалось воспроизвести проблему с 200 строк кода. В моей системе эта демонстрация была скомпилирована и работала отлично (только мерцание все еще было там, конечно). Я снял все, что не имело к этому никакого отношения. Итак, в основном у нас есть два исходных файла: менеджер экрана и менеджер игры.

экран менеджер: http://pastebin.com/WeKpxEXW

игра менеджер: http://pastebin.com/p3C5m8UN

вы можете скомпилировать этот код с помощью этого файла make (я использую портированную версию Linux " make for Windows): УК = и javac BASE = nl / jorikoolstra/jLevel CLASS_FILES = классы / $(база) / игра / GameMain.Class classes / $(BASE)/графика / ScreenManager.класс!--6-->

jLevel: $(CLASS_FILES)
    @echo Done.

classes/%.class : src/%.java
    @echo Compiling src/$*.java to $@ [command: $(CC) src/$*.java ] ...
    @$(CC) -Xlint:unchecked -d classes -classpath src src/$*.java

где исходные файлы находятся в папке .

после компиляции в байт-код игра может быть запущена с помощью следующего .bat-файла:

@set STARUP_CLASS=nl.jorikoolstra.jLevel.Game.GameMain
@set ARGUMENTS=1280 1024 32
@java -cp classes;resources %STARUP_CLASS% %ARGUMENTS%

отметим, что ARGUMENT переменная зависит от ваших собственных настроек экрана и что вы должны изменить его так, что игра отображается в правильном разрешении для экрана.

6 ответов


я вижу, почему он мерцает - - - -

BufferStrategy выполняет отдельную работу рисования из компонента paint() метод, и они, похоже, используют разные Graphics объекты, и они освежают с другой скоростью --

, когда paint() вызывается перед show(), это нормально. Но!--18-->

, когда paint() вызывается после show(), он перекрасит компонент в его первоначальный пустой вид - так происходит мигание.


это очень легко устранить мерцание: переопределить paint() метод JFrame (GameMain) как вам не нужно ничего делать (BufferStrategy может дать вам более точный контроль на материалах картины):

@Override
public void paint (Graphics g) {}

вот и все. (Я протестировал его, и он отлично работает, надеюсь, это может помочь:))


== = = = = Update =====

вместо переопределения paint() метод, лучший способ-вызвать setIgnoreRepaint(true) для JFrame (GameMain) - этот метод предназначен только для таких цели! ИСПОЛЬЗОВАТЬ!

private GameMain(String ... args)
{
    setIgnoreRepaint(true);
    .....
}

вот как я реализую двойную буферизацию, может помочь вам получить концепцию. Обратите внимание, что он реализован в JPanel, но я думаю, что он может быть реализован в других контейнерах:

TheJApplet.java:

import java.awt.*;
import javax.swing.*;

public class TheJApplet extends JApplet
{
    private Image myImage;

    java.net.URL GameURL = CheckerGameJApplet.class.getResource("GameIMG");

    String GamePath = GameURL.getPath();

    @Override
    public void init()
    {
        String GraphPath = GamePath+"/";

        File myImage_File = new File(GraphPath+"myImage.jpg");

        try
        {
            myImage = ImageIO.read(myImage_File);
        }
        catch (IOException ex)
        {
            // Add how you like to catch the IOExeption
        }

        final TheJPanel myJPanel = new TheJPanel(myImage);

        add(myJPanel);
    }
}

TheJPanel.java:

import java.awt.*;
import javax.swing.*;

public class TheJPanel extends JPanel
{
    private int screenWidth  = 500;
    private int screenHeight = 500;

    private BufferedImage BuffImg = new BufferedImage
                                         (screenWidth, 
                                          screenHeight,
                                          BufferedImage.TYPE_INT_RGB);

    private Graphics2D Graph = BuffImg.createGraphics();

    private Image myImage;

    public TheJPanel(Image myImage)
    {
        this.myImage = myImage;

        repaint();
    }

    @Override
    public void paintComponent(Graphics G)
    {
        Graphics2D Graph2D = (Graphics2D)G;

        super.paintComponent(Graph2D);

        if(BuffImg == null)
        {
            System.err.println("BuffImg is null");
        }

        Graph.drawImage(myImage, 0, 0, this);

        Graph2D.drawImage(BuffImg, 0, 0, this);
    }
}

надеюсь, это поможет, удачи.


У меня есть кросс-платформенная Java AWT-программа с анимацией. У него были проблемы с миганием, пока я строго не последовал примеру кода в в Java BufferStrategy документация. Однако я использую холст AWT, встроенный в иерархию Swing, а не полный экран, как вы. Ты можешь!--4-->посмотреть код здесь Если интересно.

еще одна вещь, чтобы отметить, что конвейер AWT использует примитивы OpenGL для хорошей производительности, и поддержка OpenGL глючит во многих видео водители. Попробуйте установить последние версии драйверов для вашей платформы.


это может сработать для вас, когда вы установите свой hwnd.createBufferStrategy(2) в своем собственном методе.


возникла проблема с Java-рендерингом прозрачного фона GIF картинки. В этом-то и проблема.


мне довольно сложно ответить на ваш вопрос без SCCSE. Мне также интересно, что делает RepaintManagerResetter.

возможно, вы захотите установить цвет фона на некоторые причудливые цвета, такие как 0xFF00FF, чтобы узнать, "очищает" ли кто-то фон до рисования. Если мерцающее изображение фиолетовое, это так - если оно содержит мусор или старые изображения, это, вероятно, двойная буферизация.

в любом случае я бы попытался убедиться, что никто не рисует ожидать себе. Во-первых, попробуйте предотвратить собственный код Windows от рисования фона окна. Установите это один раз:

/*
 * Set a Windows specific AWT property that prevents heavyweight components 
 * from erasing their background. 
 */
System.setProperty("sun.awt.noerasebackground", "true");

кроме того, убедитесь, что вы переопределяете это в своем JFrame(если вы используете компоненты Swing)

@Override
public void paintComponent(Graphics G)
{
  // do not call super.pC() here
  ...
}

Если это не помогает, укажите рабочий пример вашего кода, чтобы люди могли воспроизвести проблему.