我有一个程序,使用定时器切换图像进行动画。当程序在其最后一个图像上时,我使用一个类来创建该图像的缓冲图像,其上有文本。当显示动画的最后一个图像时,我想将显示的图像更改为缓冲图像。我无法让它发挥作用。代码就像粗体部分不在那里一样。如果我删除它上面的行,它会显示带有文本的图像,而不显示任何其他内容。我应该对我的代码进行哪些编辑来修复此问题?
执行动画的类
**import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
import java.awt.image.*;
import java.io.*;
import java.io.File;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.swing.*;
import javax.swing.*;
import javax.imageio.ImageIO;
/**
* Write a description of class Reveal here.
*
* @author (your name)
* @version (a version number or a date)
*/
public class Reveal extends JPanel
{
private JPanel panel = new JPanel(); //a panel to house the label
private JLabel label = new JLabel(); //a label to house the image
private String[] image = {"Jack in the Box 1.png","Jack in the Box 2.png","Jack in the Box 3.png","Jack in the Box 4.png","Jack in the Box 5.png","Jack in the Box 6.png","Jack in the Box 7.png"}; //an array to hold the frames of the animation
private ImageIcon[] icon = new ImageIcon[7]; //an array of icons to be the images
private JFrame f;
private TextOverlay TO;
private Timer timer;
private Timer timer2;
int x = 0;
int y = 4;
int counter = 0;
/**
* Constructor for objects of class Reveal
*/
public Reveal(String name, int number)
{
TO = new TextOverlay("Jack in the Box 7.png", name, number);
for (int h = 0; h < 7; h++){
icon[h] = new ImageIcon(image[h]);
icon[h].getImage();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
//Sets the size of the window
f.setSize(800,850);
panel = new JPanel();
label = new JLabel();
label.setIcon( icon[x] );
panel.add(label);
setVisible(true);
f.add(panel);
display(name, number);
**f.add(TO);**
}
public void display(String name, int number){
timer = new Timer(150, new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (counter > 27){
timer.stop();
timer2.start(); //starts the second half of the animation
}else{
if (x != 3){
x++;
}else{
x = 0;
}
label.setIcon( icon[x] );
counter++;
} //ends if-else
} //ends action method
}); //ends timer
timer2 = new Timer(250, new ActionListener(){
public void actionPerformed(ActionEvent e){
if (y > 6) {
timer2.stop();
}else{
label.setIcon( icon[y] );
y++;
} //ends if-else
} //ends action method
}); //ends timer2
timer.start();
}
}
**
将文本放在图像上的类
import java.io.*;
import java.awt.*;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
/**
* @see https://stackoverflow.com/questions/2658663
*/
public class TextOverlay extends JPanel {
private BufferedImage image;
private String name;
private String fileX;
private int number;
public TextOverlay(String f, String s, int n) {
name = s;
number = n;
fileX = f;
try {
image = ImageIO.read(new File(fileX));
} catch (IOException e) {
e.printStackTrace();
}
image = process(image, name, number);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
private BufferedImage process(BufferedImage old, String name, int number) {
int w = old.getWidth();
int h = old.getHeight();
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(old, 0, 0, w, h, this);
g2d.setPaint(Color.black);
g2d.setFont(new Font("Franklin Gothic Demi Cond", Font.PLAIN, 30));
String s1 = name;
String s2 = Integer.toString(number);;
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString(s1, 40, 90);
g2d.drawString(s2, 40, 140);
g2d.dispose();
return img;
}
}
所以,你似乎对Swing如何工作有误解,你可能会发现How to Use Swing Timers和Concurrency in Swing的一些帮助。
基本上,当你start
一个Timer
时,它不会在此时阻止,直到计时器结束(即使它确实如此,你的工作方式也不会像你想要的那样)。而是创建一个新线程,并在指定的时间段后,在Event Dispatching Thread上发出一个请求以执行提供的Runnable
。
这意味着当你做某事......
f.add(panel);
display(name, number);
f.add(TO);
你实际上是在qazxsw poi之上添加了qazxsw poi组件(因为框架使用的是TO
,而JLabel
位置是默认位置。
相反,在第二个计时器完成后,您需要删除标签并添加BorderLayout
组件...
CENTRE
TO
动画实际上是一个非常复杂的主题,不容易实现。
这就是为什么当遇到这些问题时,我更愿意看看已经实施的库来帮助解决这些问题。我建议你看看:
timer2 = new Timer(250, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (y > 6) {
timer2.stop();
Container parent = label.getParent();
parent.remove(label);
parent.add(TO);
parent.revalidate();
} else {
label.setIcon(icon[y]);
y++;
} //ends if-else
} //ends action method
}); //ends timer2
import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class Reveal extends JPanel {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new Reveal("Test", 5);
}
});
}
private JPanel panel = new JPanel(); //a panel to house the label
private JLabel label = new JLabel(); //a label to house the image
private ImageIcon[] icon = new ImageIcon[7]; //an array of icons to be the images
private JFrame f;
private TextOverlay TO;
private Timer timer;
private Timer timer2;
int x = 0;
int y = 4;
int counter = 0;
/**
* Constructor for objects of class Reveal
*/
public Reveal(String name, int number) {
TO = new TextOverlay("Jack in the Box 7.png", name, number);
for (int h = 0; h < 7; h++) {
icon[h] = new ImageIcon(makeImage(h));
icon[h].getImage();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
//Sets the size of the window
f.setSize(800, 850);
panel = new JPanel(new GridBagLayout());
label = new JLabel();
label.setIcon(icon[x]);
label.setBorder(new LineBorder(Color.RED));
panel.add(label);
f.add(panel);
display(name, number);
// f.add(TO);
setVisible(true);
}
public void display(String name, int number) {
timer = new Timer(150, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (counter > 27) {
timer.stop();
timer2.start(); //starts the second half of the animation
} else {
if (x != 3) {
x++;
} else {
x = 0;
}
label.setIcon(icon[x]);
counter++;
} //ends if-else
} //ends action method
}); //ends timer
timer2 = new Timer(250, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (y > 6) {
timer2.stop();
Container parent = label.getParent();
parent.remove(label);
parent.add(TO);
parent.revalidate();
} else {
label.setIcon(icon[y]);
y++;
} //ends if-else
} //ends action method
}); //ends timer2
timer.start();
}
protected BufferedImage makeImage(int h) {
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
FontMetrics fm = g2d.getFontMetrics();
String text = Integer.toString(h);
int x = (100 - fm.stringWidth(text)) / 2;
int y = ((100 - fm.getHeight()) / 2) + fm.getAscent();
g2d.setColor(Color.BLUE);
g2d.fillRect(0, 0, 100, 100);
g2d.setColor(Color.BLACK);
g2d.drawString(text, x, y);
g2d.dispose();
return img;
}
public class TextOverlay extends JPanel {
private BufferedImage image;
private String name;
private String fileX;
private int number;
public TextOverlay(String f, String s, int n) {
name = s;
number = n;
fileX = f;
image = makeImage(n);
image = process(image, name, number);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
private BufferedImage process(BufferedImage old, String name, int number) {
int w = old.getWidth();
int h = old.getHeight();
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(old, 0, 0, w, h, this);
g2d.setPaint(Color.black);
g2d.setFont(new Font("Franklin Gothic Demi Cond", Font.PLAIN, 30));
String s1 = name;
String s2 = Integer.toString(number);;
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString(s1, 40, 90);
g2d.drawString(s2, 40, 140);
g2d.dispose();
return img;
}
}
}
作为一些起点。
虽然我更喜欢使用库,但有时它不可能,或者库不符合我的整体需求......而且我喜欢涉猎......这是一种爱好。
基于我从你的代码中可以理解的东西,你试图从快速动画开始,然后慢下来直到你到达最后一帧。在动画理论中,这通常被称为缓和,更具体地说,“缓慢/缓和”。
以下借鉴了我一直在玩的一堆片段(设计一个更可重复使用的库),它将在4秒内基本上(随机)显示图像,动画放慢速度,最后呈现“幸运” “号码
nb gif动画实际上非常慢,你需要运行它才能看到差异
universal-tween-engine