gpt4 book ai didi

java - 如何修复位于另一个预先绘制的 JPanel 之上的 JPanel 上的动态移动图像的闪烁?

转载 作者:行者123 更新时间:2023-12-02 10:06:08 25 4
gpt4 key购买 nike

我在 JFrame 中制作了 2 个 JPanels,Panel 和 BackGround。我在 10 毫秒后动态绘制面板(使用计时器),但背景仅在游戏开始时绘制一次。展板负责战斗机(航天器)、弹丸和外星人的展示。 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;
}

}

这是背景:

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

}

}

我希望 Sprite 不会闪烁并且不会滞后(经过多次试验后不会发生这种情况)。

最佳答案

  1. 不要在绘画方法中调用重绘
  2. 摆脱Background 类并在一个 JPanel 中完成所有绘图。例如:
  3. 请参阅下面的示例以及 MCVE 设计
    • 整个内容可以复制/粘贴到 IDE 中并运行
    • 使用可供所有人在线使用的图像,而不是磁盘上的图像
  4. 我还会删除仅调用 repaint() 的计时器,而改为
    • 从 KeyListener 中调用重绘
    • 或使用计时器执行实际的 Sprite 移动代码(使用repaint())。如果您想要连续移动,这将很有用

MCVE 示例:

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

class Panel1 extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
public static final int DELAY = Frame1.DELAY;
private Timer timer;
private BufferedImage fighter;
private BufferedImage background;
int x, y;

public Panel1() {
timer = new Timer(DELAY, this);
try {
URL url = new URL(Frame1.SPRITE_IMAGE);
// fighter = ImageIO.read(this.getClass().getResource("fighter.png"));
fighter = ImageIO.read(url);

url = new URL(Frame1.ANDROMEDA_IMAGE);
background = ImageIO.read(url);

} catch (IOException e) {
e.printStackTrace();
}
initComponents();
timer.start();
}

public void initComponents() {
this.setSize(Frame1.WIDTH, Frame1.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);
g.drawImage(background, 0, 0, this);
g.drawImage(fighter, x, y, this);
}

@Override
public void actionPerformed(ActionEvent arg0) {
this.repaint();
}

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

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

关于java - 如何修复位于另一个预先绘制的 JPanel 之上的 JPanel 上的动态移动图像的闪烁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55323809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com