你可以...
制作一个JPanel 来绘制精灵,使其透明并将其添加到背景面板...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
BackgroundPane backgroundPane = new BackgroundPane();
backgroundPane.setLayout(new BorderLayout());
backgroundPane.add(new SpitePane());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(backgroundPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BackgroundPane extends JPanel {
private BufferedImage bgImg;
public BackgroundPane() {
try {
bgImg = ImageIO.read(...);
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return bgImg == null ? new Dimension(200, 200) : new Dimension(bgImg.getWidth(), bgImg.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - bgImg.getWidth()) / 2;
int y = (getHeight() - bgImg.getHeight()) / 2;
g2d.drawImage(bgImg, x, y, this);
g2d.dispose();
}
}
public class SpitePane extends JPanel {
private BufferedImage sprite;
public SpitePane() {
try {
sprite = ImageIO.read(...);
} catch (IOException ex) {
ex.printStackTrace();
}
setOpaque(false);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - sprite.getWidth()) / 2;
int y = (getHeight() - sprite.getHeight()) / 2;
g2d.drawImage(sprite, x, y, this);
g2d.dispose();
}
}
}
但是,问题是,你并没有真正实现任何效率,当你更新SpritePane时,它需要绘制BackgroundPane(因为绘制和透明容器的工作方式)
你可以...
同时直接在背景上绘制你的精灵...
这将产生与上面相同的结果...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
GamePane backgroundPane = new GamePane();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(backgroundPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePane extends JPanel {
private BufferedImage bgImg;
private BufferedImage sprite;
public GamePane() {
try {
bgImg = ImageIO.read(...);
sprite = ImageIO.read(...);
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return bgImg == null ? new Dimension(200, 200) : new Dimension(bgImg.getWidth(), bgImg.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - bgImg.getWidth()) / 2;
int y = (getHeight() - bgImg.getHeight()) / 2;
g2d.drawImage(bgImg, x, y, this);
x = (getWidth() - sprite.getWidth()) / 2;
y = (getHeight() - sprite.getHeight()) / 2;
g2d.drawImage(sprite, x, y, this);
g2d.dispose();
}
}
}
现在,通过一些巧妙的工作,这实际上可以更有效,假设您只重新绘制已更改的区域;)
AWT 与 Swing
好的,所以你一直在谈论Canvas/Panel 和JPanel,你需要知道这些组件的运行方式彼此之间存在显着差异。
AWT 组件 (Canvas/Panel) 被称为重量级组件,它们有自己的本地对等体,它们可以在上面进行绘制。它们不能透明,也没有 z-ordering 的概念(与 Swing 组件混合时会出现问题)。
AWT 组件确实允许您控制绘制过程(AKA 主动绘制),但这排除了将任何 Swing 组件与它们一起使用的可能性(因为 Swing 有自己的绘制过程)
Swing 组件被称为轻量级组件,它们共享它们所在的父窗口的本机对等点。默认情况下它们也是双缓冲的(这是使用BufferStrategy 和Canvas 的原因之一)并且可以是透明的。 Swing 使用所谓的被动渲染算法,这意味着重绘管理器将决定要绘制什么以及何时绘制某些内容,您可以请求更新某些内容,但您不能保证何时执行.
您的问题的答案是,这取决于。您需要决定必须具备哪些功能以及您愿意做的工作类型(主动绘画可能需要一些工作才能完成设置)以及两个系统之间的权衡。
您可以查看Painting in AWT and Swing、Performing Custom Painting 和BufferStrategy 和BufferStrategy and BufferCapabilities 了解更多详情