简体   繁体   中英

Double Buffering with Java Swing leaving a trail

The project I am working on is intended to show a moveable .gif with a background behind it. Currently if I use super.paint(g); then the character and the background painted flicker. If I don't, then it leaves a trail like the image included. I have no idea why this is happening and need help.

Java swing的图像动画

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JLabel;

public class keyboardinput extends JFrame implements ActionListener, KeyListener {
    private JPanel contentPane;

    private Image playerModelRight;
    private Image playerModelLeft;
    private Image playerModelAttackRight;
    private Image playerModelAttackLeft;
    private Image playerModelStandRight;
    private Image playerModelStandLeft;
    private Image background;
    private Image doubleBuffer;

    private int direction;

    private Timer timer;

    private boolean up;
    private boolean down;
    private boolean left;
    private boolean right;
    private boolean attack;

    private int x, y;
    private int speed = 4;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    keyboardinput frame = new keyboardinput();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public keyboardinput() {

        super("Keyboard input testing");

        x = 200;
        y = 200;

        ImageIcon playerModelIconRight = new    ImageIcon(keyboardinput.class.getResource("/images/bitdashright.gif"));
        playerModelRight = playerModelIconRight.getImage();

        ImageIcon playerModelIconLeft = new ImageIcon(keyboardinput.class.getResource("/images/bitdashleft.gif"));
        playerModelLeft = playerModelIconLeft.getImage();

        ImageIcon playerModelIconStandRight = new ImageIcon(keyboardinput.class.getResource("/images/bitdashstandright.gif"));
        playerModelStandRight = playerModelIconStandRight.getImage();

        ImageIcon playerModelIconStandLeft = new ImageIcon(keyboardinput.class.getResource("/images/bitdashstandleft.gif"));
        playerModelStandLeft = playerModelIconStandLeft.getImage();

        ImageIcon playerModelIconAttackRight = new ImageIcon(keyboardinput.class.getResource("/images/bitdashattackright.gif"));
        playerModelAttackRight = playerModelIconAttackRight.getImage();

        ImageIcon playerModelIconAttackLeft = new ImageIcon(keyboardinput.class.getResource("/images/bitdashattackleft.gif"));
        playerModelAttackLeft = playerModelIconAttackLeft.getImage();

        ImageIcon backgroundIcon = new ImageIcon(keyboardinput.class.getResource("/images/backgroundtest.png"));
        background = backgroundIcon.getImage();

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(50, 50, 800, 500);
        contentPane = new JPanel();

        addKeyListener(this);

        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        timer = new Timer(10, this);
        timer.start();
    }

    public void update(Graphics g) {
        Dimension size = getSize();
        if (doubleBuffer == null || doubleBuffer.getWidth(this) != size.width || doubleBuffer.getHeight(this) != size.height) {
            doubleBuffer = createImage(size.width, size.height);
        }

        if (doubleBuffer != null) {
            Graphics g2 = doubleBuffer.getGraphics();
            paint(g2);
            g2.dispose();

            g.drawImage(doubleBuffer, 0, 0, null);
        } else {
            paint(g);
        }
    }

    public void paint(Graphics g) {
        super.paintComponents(g);
        if (attack) {
            if (direction == 1)
                g.drawImage(playerModelAttackRight, x, y, this);
            if (direction == 0) {
                x -= 15;
                g.drawImage(playerModelAttackLeft, x, y, this);
                x += 15;
            }
        } else if (left && right)
            g.drawImage(playerModelStandRight, x, y, this);
        else if (right)
            g.drawImage(playerModelRight, x, y, this);
        else if (left)
            g.drawImage(playerModelLeft, x, y, this);
        else {
            if (direction == 1)
                g.drawImage(playerModelStandRight, x, y, this);
            if (direction == 0)
                g.drawImage(playerModelStandLeft, x, y, this);
        }
        // g.drawImage(background, 0, 0, this);

    }

    public void actionPerformed(ActionEvent arg0) {
        if (attack)
            return;
        if (up && y > 235)
            y -= speed;
        if (down && y < 430)
            y += speed;
        if (left && x > -10)
            x -= speed;
        if (right && x < 750)
            x += speed;
        repaint();
        System.out.println(x + ", " + y);
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            right = true;
            direction = 1;
        }
        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            left = true;
            direction = 0;
        }
        if (e.getKeyCode() == KeyEvent.VK_DOWN)
            down = true;
        if (e.getKeyCode() == KeyEvent.VK_UP)
            up = true;
        if (e.getKeyCode() == KeyEvent.VK_SPACE)
            attack = true;

    }

    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_RIGHT)
            right = false;
        if (e.getKeyCode() == KeyEvent.VK_LEFT)
            left = false;
        if (e.getKeyCode() == KeyEvent.VK_DOWN)
            down = false;
        if (e.getKeyCode() == KeyEvent.VK_UP)
            up = false;
        if (e.getKeyCode() == KeyEvent.VK_SPACE)
            attack = false;
    }

    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

}
public void paint(Graphics g) {
    super.paintComponents(g);
  1. This is guaranteed to bring trouble. Don't call the wrong super method inside your override.
  2. Don't draw directly in the JFrame but rather in the paintComponent method of a JPanel.
  3. Don't override update in a Swing program.

Do check out the tutorials:

  1. You've broken the paint chain, calling super.paintComponents(g); from within paint . This will cause no end of weird and wonderful painting issues
  2. You should avoid overriding paint of top level containers, because they aren't double buffered, but Swing components are, so you really should use a JPanel and override it's paintComponent method instead. You should also avoid painting to top level containers like JFrame like this, as you it will allow you to paint under the frame borders, never pretty, and JFrame has a number of other, overlapping components which reside ontop of it, which could cause issues with when they are repainted (as a child component may not notify it's parent container when it's repainted)
  3. You've not "reset" the buffer before painting to it, so you are getting accumulative updates

You "could" add g2.fillRect(0, 0, getWidth(), getHeight()); to your code before you call paint in your update method, but as I've already said, you're wasting a lot of time and effort on something that has already been done and provided by the API, if you use it correctly

Take a closer look at Performing Custom Painting and Painting in AWT and Swing for how painting should be done

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