我正在循环几个png来为java splashscreen创建动画。
我使用此
启动动画java -splash:images/anim.png SplashDemo
并使用课堂内的png。你可以在这里找到课程 - http://pastebin.com/UWm25QfY
我唯一的问题是我选择使用anim.png启动动画的alpha是最终的,并且后来被覆盖了所有的png
我尝试了AlphaComposite.Clear,Src,SrcOver,但没有任何效果。如果我以0不透明度加载png,那么整个动画就会消失。谁能告诉我如何摆脱这个?
答案 0 :(得分:1)
因此,您遇到的问题与以下事实有关:您正在绘制的Graphics
上下文实际上从未在更新之间“清理”或“休息”。我知道,这是一种痛苦,但确实如此。
关于您唯一的选择是在绘制下一张图像之前实际重置每个周期的输出。
幸运的是,SplashScreen
实际上为URL
提供了背景图片。这允许我们自己加载图像并根据需要重新绘制到表面上。
您还应该尽最大努力将Graphics
上下文恢复到您找到它的状态(当然,除了您绘制的内容之外)。这可以通过在绘制之前制作图形状态的副本来完成...
Graphics2D g2d = (Graphics2D)g.create();
// Do you're painting here...
// Release the state when you're done.
g2d.dispose();
import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.SplashScreen;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class SplashScreen100 extends Frame implements ActionListener {
static ArrayList<Image> imgs;
private static final long serialVersionUID = 1L;
private BufferedImage background;
protected void renderSplashFrame(Graphics2D g, Image bg) {
// Get the splash screen size...
Dimension size = SplashScreen.getSplashScreen().getSize();
int width = size.width;
int height = size.height;
// Center the image within the splash screen
int x = (width - bg.getWidth(null)) / 2;
int y = (height - bg.getHeight(null)) / 2;
Graphics2D g2d = (Graphics2D) g.create();
// Draw the background
g2d.drawImage(background, 0, 0, null);
// Apply alpha composite
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
// Draw the image...
g2d.drawImage(bg, x, y, null);
g2d.dispose();
}
public SplashScreen100() {
super("SplashScreen demo");
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
return;
}
Graphics2D g = splash.createGraphics();
if (g == null) {
System.out.println("g is null");
return;
}
try {
background = ImageIO.read(splash.getImageURL());
for (Image img : imgs) {
renderSplashFrame(g, img);
splash.update();
// I put this in to slow the updates down...
try {
Thread.sleep(250);
} catch (InterruptedException ex) {
Logger.getLogger(SplashScreen100.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (IOException exp) {
exp.printStackTrace();
}
splash.close();
}
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
public static void main(String args[]) {
System.setProperty("sun.java2d.opengl", "True");
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
GraphicsConfiguration config = device.getDefaultConfiguration();
imgs = new ArrayList<Image>();
for (File file : new File("\path\to\images").listFiles()) {
if (file.getName().toLowerCase().endsWith(".png")) {
try {
Image buffy = ImageIO.read(file);
imgs.add(buffy);
} catch (IOException e) {
e.printStackTrace();
}
}
}
SplashScreen100 test = new SplashScreen100();
}
}
使用其他方法更新
基本上,随着图像尺寸的增加,更新速度会降低。相反,我只是创建自己的,以便您可以更好地控制更新过程。
这使用JWindow
作为基本窗口,并使用自定义JPanel
作为主要显示。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import static splashscreen.MySplashScreen.createCompatibleImage;
import static splashscreen.MySplashScreen.getGraphicsConfiguration;
public class DifferentSplashScreen {
public static void main(String[] args) {
new DifferentSplashScreen();
}
public DifferentSplashScreen() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JWindow frame = new JWindow();
frame.setAlwaysOnTop(true);
frame.setLayout(new BorderLayout());
frame.add(new SplashPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SplashPane extends JPanel {
private BufferedImage background;
private List<BufferedImage> frames;
private int frameIndex;
private BufferedImage currentFrame;
public SplashPane() {
try {
background = ImageIO.read(new File("C:\\Users\\shane\\Dropbox\\MegaTokyo\\2005-09-29-3957.jpeg"));
frames = new ArrayList<>(40);
List<BufferedImage> images = new ArrayList<>(20);
for (int index = 0; index < 20; index++) {
try {
BufferedImage buffy = ImageIO.read(new File(index + ".png"));
images.add(createCompatibleImage(buffy));
} catch (IOException e) {
e.printStackTrace();
}
}
frames.addAll(images);
Collections.reverse(images);
frames.addAll(images);
} catch (IOException ex) {
ex.printStackTrace();
}
final Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (frameIndex >= frames.size()) {
frameIndex = 0;
}
currentFrame = frames.get(frameIndex);
frameIndex++;
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
if (currentFrame != null) {
x = (getWidth() - currentFrame.getWidth()) / 2;
y = (getHeight() - currentFrame.getHeight()) / 2;
g2d.drawImage(currentFrame, x, y, this);
}
g2d.dispose();
}
}
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
public static BufferedImage createCompatibleImage(BufferedImage master) {
BufferedImage img = createCompatibleImage(master, master.getWidth(), master.getHeight());
Graphics2D g2d = img.createGraphics();
g2d.drawImage(master, 0, 0, null);
g2d.dispose();
return img;
}
public static BufferedImage createCompatibleImage(BufferedImage image,
int width, int height) {
return getGraphicsConfiguration().createCompatibleImage(width, height, image.getTransparency());
}
}
它还将所有图像转换为“设备兼容”图像,这意味着它们应该渲染得更快,因为它们的颜色调色板不需要动态转换。
背景图像为1563x1250,面部图像为300x300(具有不同的alpha级别)。
使用这个例子,我得到了一个没有问题的稳定更新,使用与SplashScreen
相同的图像,这非常可怕......