简体   繁体   中英

JFrame repainting image blinking

I am having an issue with the command super.paintComponents(g); when updating a JFrame. The issue I am having is that the image I am loading is blinking while the code is running. I am pretty sure that the code is double buffering and have not found any helpful resource online to solve this issue. This is my first question so please tolerate any formatting errors.

Here is my entire code (snippets below):

public class GAME extends JFrame implements KeyListener, MouseMotionListener {
int mouseX, mouseY;

public static ArrayList<Images> images = new ArrayList<Images>();
public static String lastKeyPressed = null;

public GAME() {
    this.addMouseMotionListener(this);
    this.addKeyListener(this);
}

public void mouseDragged(MouseEvent e) {
    mouseX = e.getX();
    mouseY = e.getY();
}

public void mouseMoved(MouseEvent e) {
    mouseX = e.getX();
    mouseY = e.getY();
}

public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == e.VK_LEFT) {
        lastKeyPressed = "LEFT";
    } else if (e.getKeyCode() == e.VK_RIGHT) {
        lastKeyPressed = "RIGHT";
    } else if (e.getKeyCode() == e.VK_UP) {
        lastKeyPressed = "UP";
    } else if (e.getKeyCode() == e.VK_DOWN) {
        lastKeyPressed = "DOWN";
    }
}

public void keyReleased(KeyEvent e) {

}

public void keyTyped(KeyEvent e) {

}

@Override
public void paint(Graphics g) {
    super.paintComponents(g);
    for (int i = 0; i < images.size(); i++) {
        g.drawImage(images.get(i).img, images.get(i).xpos, images.get(i).ypos, null);
    }
}

public static void main(String[] args) throws IOException, InterruptedException {
    GAME frame = new GAME();
    Dimension dim = new Dimension(800, 600);
    frame.setPreferredSize(dim);
    frame.setSize(dim);
    frame.setResizable(false);
    frame.setTitle("GAME");
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    Images test = new Images("unnamed.png");
    images.add(test);
    while (true) {
        if (lastKeyPressed == "LEFT") {
            test.xpos -= 5;
            lastKeyPressed = null;
        } else if (lastKeyPressed == "RIGHT") {
            test.xpos += 5;
            lastKeyPressed = null;
        } else if (lastKeyPressed == "UP") {
            test.ypos -= 5;
            lastKeyPressed = null;
        } else if (lastKeyPressed == "DOWN") {
            test.ypos += 5;
            lastKeyPressed = null;
        }
        frame.repaint();
        Thread.sleep(100);
    }
}

}

Here is the images class:

public class Images {

String name;
BufferedImage img;
int xpos;
int ypos;

public Images (String Name) throws IOException{
    name = Name;
    xpos = 40;
    ypos = 90;
    System.out.println(name);
    System.out.println("PATH: " + GAME.class.getResource(name));
    URL file = getClass().getClassLoader().getResource(name);
    img = ImageIO.read(file);
}
}

What you probably only want to see is the following:

My paint method:

@Override
public void paint(Graphics g) {
    super.paintComponents(g);
    for (int i = 0; i < images.size(); i++) {
        g.drawImage(images.get(i).img, images.get(i).xpos, images.get(i).ypos, null);
    }
}

And the block of code in the main class that is running the game:

Images test = new Images("unnamed.png");
    images.add(test);
    while (true) {
        if (lastKeyPressed == "LEFT") {
            test.xpos -= 5;
            lastKeyPressed = null;
        } else if (lastKeyPressed == "RIGHT") {
            test.xpos += 5;
            lastKeyPressed = null;
        } else if (lastKeyPressed == "UP") {
            test.ypos -= 5;
            lastKeyPressed = null;
        } else if (lastKeyPressed == "DOWN") {
            test.ypos += 5;
            lastKeyPressed = null;
        }
        frame.repaint();
        Thread.sleep(100);
    }

(I added the Thread.sleep because it seemed to decrease the rate at which the blinking occurred)

Here is a gif of what is happening (I just used the first Google result for 'test' for the image): http://i.imgur.com/WjLCSvu.gif?1

I appreciate any help and general suggestions to better my code. Thank you.

Don't override paint of top level containers like JFrame there aren't double buffered, instead, use a JPanel and override its paintComponent method. JPanel is double buffered by default.

Then, add the panel to what ever container you want

Don't forget to call it's super method ( super.paintComponent ) before you do any custom painting.

Take a closer look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing

This is just one reason why you shouldn't (extend from JFrame and) override paint of top level containers, take a look at

for some more

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM