2014-12-01 66 views
1

我有这个非常糟糕的精灵表,我基本上只是一堆圆形和椭圆形,所以我可以掌握精灵动画。尝试在JFrame上绘制精灵时出现drawImage错误

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语句,因为它也涉及到定时器。

+0

作为参考,下面是使用'getSubimage()'的工作[示例](http://stackoverflow.com/a/3078354/230513)。 – trashgod 2014-12-01 21:57:25

+1

第一个错误 - 'Graphics g = getGraphics();'< - 这不是绘画在Swing中的工作方式,绘画由负责安排绘画事件的RepaintManager控制。如果需要,您将调用组件的“绘画”方法,然后对一系列方法进行分类,以促进实际的绘画过程。请参阅[执行自定义绘画](http://docs.oracle.com/javase/tutorial/uiswing/painting/)和[在AWT和Swing中绘画](http://www.oracle.com/technetwork/java/painting -140037.html)了解更多详情 – MadProgrammer 2014-12-01 23:51:18

+0

1)为了更快地获得更好的帮助,请发布[MCVE](http://stackoverflow.com/help/mcve)(最小完整可验证示例)或[SSCCE](http:// www .sscce.org /)(简短,独立,正确的例子)。 2)获取图像的一种方法是通过[本问答](http://stackoverflow.com/q/19209650/418556)中的图像进行热链接。 – 2014-12-02 00:15:31

回答

2

由于您没有提供可运行示例,因此我创建了一个示例以显示如何正确编写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类的运行方法。我创建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组件,就像我在DraawingPanel类一样。否则使用Swing组件。

这是整个可运行的CircleSprite类。您可以将其用作未来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) { 

      } 
     } 

    } 

}