如何解决另一个预先绘制的JPanel之上的JPanel上动态运动图像的闪烁?

时间:2019-03-24 12:29:49

标签: java swing user-interface jframe jpanel

我在JFrame中制作了 2个JPanels (面板和BackGround)。我在10毫秒后(使用计时器)动态绘制面板,但是BackGround在游戏开始时只绘制了一次。小组负责展示战斗机(航天器),射弹和外星人。 BackGround负责显示非动态背景场景。 paintComponent(Graphics)方法可以绘制战斗机和弹丸,但在更新时会闪烁。有人可以找到原因。

这是我的画框:

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Frame extends JFrame {
    private static final long serialVersionUID = 1L;

    public static final int WIDTH = 1280;
    public static final int HEIGHT = 720;

    public static final int DELAY = 10;

    private Panel panel;
    private Background bg;

    public Frame() {

        panel = new Panel();
        bg = new Background();

        initComponents();
    }

    public void initComponents() {

        this.setSize(WIDTH, HEIGHT);

        this.add(bg);
        this.add(panel);

        this.setLocationRelativeTo(null);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.addKeyListener(new KeyAdapter() {

            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode() == KeyEvent.VK_LEFT) panel.moveLeft();
                else if(e.getKeyCode() == KeyEvent.VK_RIGHT) panel.moveRight();
            }

        });

    }

    public static void main(String args[]) {

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Frame().setVisible(true);
            }
        });

    }

}

这是我的小组:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Panel extends JPanel implements ActionListener {
    private static final long serialVersionUID = 1L;

    public static final int DELAY = Frame.DELAY;

    private Timer timer;
    private BufferedImage fighter;

    int x, y;

    public Panel() {

        timer = new Timer(DELAY, this);
        try {
            fighter = ImageIO.read(this.getClass().getResource("fighter.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        initComponents();

        timer.start();
    }

    public void initComponents() {

        this.setSize(Frame.WIDTH, Frame.HEIGHT);
        this.setDoubleBuffered(true);
        this.setBackground(new Color(0, 0, 0, 0));

        x = 150;
        y = 200;

    }


    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        doDrawing(g2d);

    }



    private void doDrawing(Graphics2D g2d) {

        g2d.drawImage(fighter, x, y, null);

    }

    @Override
    public void actionPerformed(ActionEvent arg0) {

        this.repaint();
    }

    public void moveLeft() {
        x -= 10;
    }

    public void moveRight() {
        x += 10;
    }

}

这是BackGround:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.Timer;


public class Background extends JPanel implements ActionListener{
    private static final long serialVersionUID = 1L;

    private BufferedImage backGround;
    private Timer timer;
    public Background() {

        this.setSize(Frame.WIDTH, Frame.HEIGHT);
        this.setBackground(new Color(0, 0, 0, 0));

        timer = new Timer(Frame.DELAY, this);

        try {
            backGround = ImageIO.read(this.getClass().getResource("background.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        timer.start();

    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawImage(backGround, 0, 0, null);

    }

    @Override
    public void actionPerformed(ActionEvent e) {

        this.repaint();

    }

}

我希望精灵不闪烁不滞后(经过大量试验后不会发生)。

1 个答案:

答案 0 :(得分:1)

  1. 请勿在绘画方法中调用重绘
  2. 摆脱Background类,并在 one JPanel中进行所有绘制。例如:
  3. 请参见下面的示例以及MCVE设计
    • 整个内容都可以复制/粘贴到IDE中并运行
    • 使用所有在线(而不是磁盘)上可用的图像
  4. 我还将删除仅调用#include "inquire.h" int main(int argc, char *argv[]) { int *pointer; char *list[] = {"Hello1", "Hello2", "Hello3", "Hello4", "Hello5", NULL}; pointer = multiChoice(list); printf("Choices:\n"); for (int i = 0; pointer[i] >= 0; i++) { printf("%s\n", list[pointer[i]]); } } 的Timer,而是
    • 在KeyListener中调用重绘
    • 或使用计时器执行实际的精灵移动代码(使用repaint())。如果您要连续移动,这将很有用

MCVE示例:

repaint()

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.*;

public class Frame1 extends JFrame {
    // Image attribution:
    // By Adam Evans - M31, the Andromeda Galaxy (now with h-alpha)
    // Uploaded by NotFromUtrecht, CC BY 2.0,
    // https://commons.wikimedia.org/w/index.php?curid=12654493
    public static final String ANDROMEDA_IMAGE = "https://upload.wikimedia.org/wikipedia/commons/"
            + "thumb/9/98/Andromeda_Galaxy_%28with_h-alpha%29.jpg/"
            + "1280px-Andromeda_Galaxy_%28with_h-alpha%29.jpg";
    public static final String SPRITE_IMAGE = "https://upload.wikimedia.org/wikipedia/commons/"
            + "thumb/a/a1/Glossy_3d_blue_blue2.png/" + "120px-Glossy_3d_blue_blue2.png";

    private static final long serialVersionUID = 1L;
    public static final int WIDTH = 1280;
    public static final int HEIGHT = 720;
    public static final int DELAY = 10;
    private Panel1 panel;
    // private Background bg;

    public Frame1() {
        panel = new Panel1();
        // bg = new Background();
        initComponents();
    }

    public void initComponents() {
        this.setSize(WIDTH, HEIGHT);
        // this.add(bg);
        this.add(panel);
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_LEFT)
                    panel.moveLeft();
                else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
                    panel.moveRight();
            }
        });
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Frame1().setVisible(true);
            }
        });
    }
}