Java Canvas repaint() 闪烁
Java Canvas repaint() is flickering
所以我终于得到了一个 Canvas 来按照我想要的方式工作,但它不断闪烁,repaint() 是每秒 运行 20 次,当我完成它时闪烁确实减少了 运行每秒10次。
package pd.data;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import pd.areas.MainMenu;
@SuppressWarnings("serial")
public class Main extends JFrame implements Runnable {
private JPanel contentPane = new JPanel();
private Thread gameThread = new Thread(this);
public boolean running = false;
@SuppressWarnings("unused")
private int current = PDU.PD_MAIN_MENU;
private MainMenu mainmenu;
public Main() {main.setTitle("PD");
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setLocation(SPU.screenWidth / 2 - SPU.windowSize.width / 2,
SPU.screenHeight / 2 - SPU.windowSize.height / 2);
main.setResizable(false);
main.setVisible(true);
contentPane.setLayout(new BorderLayout(0, 0));
contentPane.setPreferredSize(SPU.windowSize);
main.setContentPane(contentPane);
main.pack();
mainmenu = new MainMenu();
contentPane.add(mainmenu, BorderLayout.CENTER);
this.gameThread.start();
}
@Override
public void run() {
running = true;
while (running) {
{
mainmenu.repaint();
}
try {
Thread.sleep(SPU.TSU);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Main();
}
}
下面是我的主菜单 class:
package pd.areas;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
@SuppressWarnings("serial")
public class MainMenu extends Canvas{
BufferedImage img = null;
public MainMenu() {
this.setBackground(Color.BLACK);
}
public void paint(Graphics graphics){
try {
img = ImageIO.read(this.getClass().getResource(
"/image.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
graphics.drawImage(img, this.getWidth() / 2 - img.getWidth()/2, 50, null);
}
}
虽然闪烁实际上是一个很好的效果,但它会影响整个 canvas 而不仅仅是我猜测的图像,我该如何解决闪烁?
- 不要使用 java.awt.Canvas。请改用 JPanel。
- 在 JPanel 的 paintComponent 方法中绘制。
- 不要忘记调用你的 super 的绘画方法,
paintComponent
会是 super.paintComponent(graphics)
- 永远不要 尝试从任何绘画方法中读入图像。这会减慢绘画速度并使您的程序看起来反应迟钝。为什么要一遍又一遍地阅读同一张图片?在中读取一次并将其保存到变量中。
虽然这个帖子是 5 年前打开的,但对于 Java SE 的新手来说仍然是个问题。
我自己也遇到了与 Canvas 相同的问题,但没有足够的信心切换到 javax 组件,因为我想起了一个名为 JVLC 的 VLC 项目,它使用 Canvas 完美地呈现视频(当然jvlc 使用一些本机代码)。
提示 1:也许最好改用 JPanel。
提示2:在游戏系统中,最好使用游戏引擎(它会节省很多时间)。
提示 3:在游戏系统中,实施 fps 机制而不是在每次更改时调用 repaint()。
提示 4: 如果您必须在 paint() 实现中调用超过 10 行代码,您将减慢它的速度。最好为您需要对应用程序进行的每个图形更改绘制到 BufferedImage,然后让 paint() 实现本身仅绘制图像本身。这应该可以很好地配合 fps 机制,并且会减少任何闪烁的可能性。
所以我终于得到了一个 Canvas 来按照我想要的方式工作,但它不断闪烁,repaint() 是每秒 运行 20 次,当我完成它时闪烁确实减少了 运行每秒10次。
package pd.data;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import pd.areas.MainMenu;
@SuppressWarnings("serial")
public class Main extends JFrame implements Runnable {
private JPanel contentPane = new JPanel();
private Thread gameThread = new Thread(this);
public boolean running = false;
@SuppressWarnings("unused")
private int current = PDU.PD_MAIN_MENU;
private MainMenu mainmenu;
public Main() {main.setTitle("PD");
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setLocation(SPU.screenWidth / 2 - SPU.windowSize.width / 2,
SPU.screenHeight / 2 - SPU.windowSize.height / 2);
main.setResizable(false);
main.setVisible(true);
contentPane.setLayout(new BorderLayout(0, 0));
contentPane.setPreferredSize(SPU.windowSize);
main.setContentPane(contentPane);
main.pack();
mainmenu = new MainMenu();
contentPane.add(mainmenu, BorderLayout.CENTER);
this.gameThread.start();
}
@Override
public void run() {
running = true;
while (running) {
{
mainmenu.repaint();
}
try {
Thread.sleep(SPU.TSU);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Main();
}
}
下面是我的主菜单 class:
package pd.areas;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
@SuppressWarnings("serial")
public class MainMenu extends Canvas{
BufferedImage img = null;
public MainMenu() {
this.setBackground(Color.BLACK);
}
public void paint(Graphics graphics){
try {
img = ImageIO.read(this.getClass().getResource(
"/image.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
graphics.drawImage(img, this.getWidth() / 2 - img.getWidth()/2, 50, null);
}
}
虽然闪烁实际上是一个很好的效果,但它会影响整个 canvas 而不仅仅是我猜测的图像,我该如何解决闪烁?
- 不要使用 java.awt.Canvas。请改用 JPanel。
- 在 JPanel 的 paintComponent 方法中绘制。
- 不要忘记调用你的 super 的绘画方法,
paintComponent
会是super.paintComponent(graphics)
- 永远不要 尝试从任何绘画方法中读入图像。这会减慢绘画速度并使您的程序看起来反应迟钝。为什么要一遍又一遍地阅读同一张图片?在中读取一次并将其保存到变量中。
虽然这个帖子是 5 年前打开的,但对于 Java SE 的新手来说仍然是个问题。
我自己也遇到了与 Canvas 相同的问题,但没有足够的信心切换到 javax 组件,因为我想起了一个名为 JVLC 的 VLC 项目,它使用 Canvas 完美地呈现视频(当然jvlc 使用一些本机代码)。
提示 1:也许最好改用 JPanel。
提示2:在游戏系统中,最好使用游戏引擎(它会节省很多时间)。
提示 3:在游戏系统中,实施 fps 机制而不是在每次更改时调用 repaint()。
提示 4: 如果您必须在 paint() 实现中调用超过 10 行代码,您将减慢它的速度。最好为您需要对应用程序进行的每个图形更改绘制到 BufferedImage,然后让 paint() 实现本身仅绘制图像本身。这应该可以很好地配合 fps 机制,并且会减少任何闪烁的可能性。