我制作了这个非常蹩脚的 Sprite 表,它基本上只是一堆圆形和椭圆形,所以我可以掌握 Sprite 动画。
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class CircleSprite extends JFrame implements ActionListener, Runnable{
BufferedImage circles;
BufferedImage[] test;
Timer timer;
int cycle = 0;
Graphics g = getGraphics();
public void asd(){
setSize(500,500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
circles = ImageIO.read(new File("CircleTest.png"));
} catch (IOException e) {
e.printStackTrace();
}
final int width = 206;
final int height = 206;
final int rows= 2;
final int columns = 3;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test = new BufferedImage[rows * columns];
try{
for(int i = 0; i < rows; i++)
for(int j = 0;j<columns;j++)
{
test[i*columns + j] = circles.getSubimage(j * width, i * height, width, height);
}
}catch(Exception e){
e.printStackTrace();
}
timer = new Timer(500, this);
setVisible(true);
}
public void actionPerformed(ActionEvent e){
//0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, etc.
repaint();
g.drawImage(test[cycle], 25, 25, null);
if(cycle >= 5){
cycle--;
}
if(cycle <=0){
cycle++;
}
}
public void run(){
asd();
while(timer.isRunning() == false && this.isVisible() == true){
timer.start();
try {
CircleSpriteRun.t1.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
错误发生在这里:g.drawImage(test[cycle], 25, 25, null);
起初我认为这与 ImageObserver 为空有关,进一步研究它,我错了。现在,我认为这可能是因为计时器的原因,但我对计时器了解不多,更不用说 swing
了。
这一切都在另一个类中执行的Thread
上运行,并且它也可能与run
中的while
语句有关方法,因为这还涉及到计时器。
最佳答案
由于您没有提供可运行的示例,因此我创建了一个示例来展示如何正确编写 Swing 应用程序代码。
首先,您必须使用 SwingUtilities.invokeLater 方法启动 Swing 应用程序。以下是我如何启动 CircleSprite 类。
public static void main(String[] args) {
SwingUtilities.invokeLater(new CircleSprite());
}
其次,您应该使用 JPanel 进行绘图,而不是 JFrame。这是我创建的 DrawingPanel。我的 CircleSprite 版本每 2 秒在随机位置绘制一个圆圈。
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -4603711384104715819L;
private int x;
private int y;
private BufferedImage image;
public DrawingPanel(BufferedImage image) {
this.image = image;
this.x = 0;
this.y = 0;
setPreferredSize(new Dimension(500, 500));
}
public void setPoint(int x, int y) {
this.x = x;
this.y = y;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, x, y, null);
}
}
第三,在使用 Swing GUI 执行任何操作之前先创建 Swing GUI。这是 CircleSprite 类的 run 方法。我创建 GUI,然后启动执行随机绘图的线程。
public void run() {
circle = createCircle();
frame = new JFrame("Circle Sprite");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingPanel = new DrawingPanel(circle);
frame.add(drawingPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
new Thread(new RandomDraw(drawingPanel)).start();
}
第四,只有当您想要重写方法时才扩展 Swing 组件,就像我在 DrawingPanel 类中所做的那样。否则您可以使用 Swing 组件。
这是整个可运行的 CircleSprite 类。您可以将其用作 future Swing 应用程序的模型。
package com.ggl.testing;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CircleSprite implements Runnable {
private BufferedImage circle;
private DrawingPanel drawingPanel;
private JFrame frame;
@Override
public void run() {
circle = createCircle();
frame = new JFrame("Circle Sprite");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingPanel = new DrawingPanel(circle);
frame.add(drawingPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
new Thread(new RandomDraw(drawingPanel)).start();
}
private BufferedImage createCircle() {
BufferedImage image = new BufferedImage(100, 100,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, 100, 100);
g.setColor(Color.BLUE);
g.fillOval(10, 10, 80, 80);
g.dispose();
return image;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new CircleSprite());
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -4603711384104715819L;
private int x;
private int y;
private BufferedImage image;
public DrawingPanel(BufferedImage image) {
this.image = image;
this.x = 0;
this.y = 0;
setPreferredSize(new Dimension(500, 500));
}
public void setPoint(int x, int y) {
this.x = x;
this.y = y;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, x, y, null);
}
}
public class RandomDraw implements Runnable {
private DrawingPanel drawingPanel;
private Random random;
public RandomDraw(DrawingPanel drawingPanel) {
this.drawingPanel = drawingPanel;
this.random = new Random();
}
@Override
public void run() {
while (true) {
sleep();
int x = random.nextInt(400);
int y = random.nextInt(400);
drawingPanel.setPoint(x, y);
}
}
private void sleep() {
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
}
}
}
}
关于java - 尝试将 Sprite 绘制到 JFrame 上时发生 drawImage 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27236897/