Jori
Jori

Reputation: 1152

Java graphics are flashing

Okay, I understand your need for an SSCCE, so I created (my first) one.

I managed to replicate the problem with under 200 lines of code. On my system this demo compiled and ran perfectly (only the flickering was still there of course). I stripped everything that had nothing to do with it. So basically we have two source files now: the screen manager and the game manager.

The screen manager: http://pastebin.com/WeKpxEXW

The game manager: http://pastebin.com/p3C5m8UN

You can compile this code with this make file (I use a ported version of Linux' make for Windows): CC = javac BASE = nl/jorikoolstra/jLevel CLASS_FILES = classes/$(BASE)/Game/GameMain.class classes/$(BASE)/Graphics/ScreenManager.class

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

Where the source files are placed in the /src directory and the classes in the /classes directory.

After compilation to byte-code the game can be started using the following .bat file:

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

Note that the ARGUMENT variable depends on your own screen settings and that you have to change it so that the game is displayed in the right resolution for your screen.

Upvotes: 10

Views: 10818

Answers (6)

bill mee
bill mee

Reputation: 19

There was a problem with Java rendering transparent background GIF images. That could be the problem.

Upvotes: 1

Eveli
Eveli

Reputation: 498

It may work for you, when you set your hwnd.createBufferStrategy(2) in its own method.

Upvotes: 1

shuangwhywhy
shuangwhywhy

Reputation: 5625

I see why it is flickering ----

BufferStrategy is doing a separate painting job from the Component's paint() method and they seem to use different Graphics objects and they are refreshing at a different rate --

when paint() is invoked before show(), it's fine. But

when paint() is invoked after show(), it will repaint the component to its initial blank look -- so flashing happens.


It's very easy to eliminate the flickering: override paint() method of your JFrame (GameMain) as you don't need it to do anything (BufferStrategy can give you more precise control on painting stuffs):

@Override
public void paint (Graphics g) {}

That's all. (I have tested it and it works fine, hope this may help :))


===== Update =====

Instead of overriding paint() method, a better way is to call setIgnoreRepaint(true) for your JFrame (GameMain) -- this method is just designed for such purposes! USE IT!

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

Upvotes: 8

Gene
Gene

Reputation: 46960

I have a cross-platform Java AWT-based program with animation. It had flashing problems until I strictly followed the example code at in the Java BufferStrategy documentation. However I'm using an AWT Canvas embedded in a Swing hierarchy, not full screen as you. You can see the code here if interested.

Another thing to note is that the AWT pipeline uses OpenGL primitives for good performance, and OpenGL support is buggy in many video drivers. Try installing latest versions of drivers for your platform.

Upvotes: 1

msteiger
msteiger

Reputation: 2044

I find it rather difficult to answer your question without an SCCSE. I also wonder what the RepaintManagerResetter does.

You might want to set your background color to some fancy colors like 0xFF00FF to find out if someone "clears" the background before the drawing happens. If the flicker image is purple, it's that - if it contains garbage or old images, it's probably the double-buffering.

In any case I would try to ensure that noone draws expect yourself. First, try to prevent native Windows code from drawing the window background. Set this once:

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

Also, make sure that you override this in your JFrame(if you are using Swing components)

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

If that doesn't help, please provide a working example of your code, so people can reproduce the problem.

Upvotes: 0

Shikatsu
Shikatsu

Reputation: 307

This is how i implement double buffering, might help you get the concept. Note it's implemented in a JPanel, but i think it can be implemented in other containers:

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

Hope this helps, good luck.

Upvotes: 1

Related Questions