2012-11-16 118 views
1

我想要使用java的Graphics2D在屏幕上绘制图像。这是我正在使用的代码。我希望看到一个图像稳定地在屏幕上移动。目前我可以看到图像,但除非我调整窗口大小,否则它不会移动,在这种情况下,它会移动。我已经勾画出下面的课程。使用Graphics2D绘制图像

public class Tester extends JFrame { 

    private static final long serialVersionUID = -3179467003801103750L; 
    private Component myComponent; 
    public static final int ONE_SECOND = 1000; 
    public static final int FRAMES_PER_SECOND = 20; 

    private Timer myTimer; 

    public Tester (Component component, String title) { 
     super(title); 
     myComponent = component; 
    } 

    public void start() { 

     myTimer = new Timer(ONE_SECOND/FRAMES_PER_SECOND, new ActionListener() { 
      @Override 
      public void actionPerformed (ActionEvent e) { 
       repaint(); 
      } 
     }); 
     myTimer.start(); 
    } 

    @Override 
    public void paint (Graphics pen) { 
     if (myComponent != null) { 
      myComponent.paint(pen); 
     } 
    } 

} 

传递到测试组件对象是以下类:

public class LevelBoard extends Canvas implements ISavable { 

    private static final long serialVersionUID = -3528519211577278934L; 

    @Override 
    public void paint (Graphics pen) { 
     for (Sprite s : mySprites) { 
      s.paint((Graphics2D) pen); 
     } 
    } 

    protected void add (Sprite sprite) { 
     mySprites.add(sprite); 
    } 

我已经确保这个类只有一个,我已经加雪碧。 Sprite类大致如下:

public class Sprite { 

    private Image myImage; 
    private int myX, myY; 

    public Sprite() { 
     URL path = getClass().getResource("/images/Bowser.png"); 
     ImageIcon img = new ImageIcon(path); 
     myImage = img.getImage(); 

    } 

    public void update() { 
     myX += 5; 
     myY += 5; 
    } 

    public void paint (Graphics2D pen) { 
     update(); 
     pen.drawImage(myImage, myX, myY,null); 
    } 

但是,我看到屏幕上只有库巴的静止图像。除非调整窗口大小,否则他不会移动。我知道Sprite类中的paint(Graphics2D pen)方法正在以特定间隔被调用(因为Tester类中的Timer)。但是,即使x和y位置每次增加5。精灵不移动。为什么不?我如何解决它?我只是试图测试我的程序的一些其他功能,所以我真的只是需要启动和运行。我真的不在乎如何。

+0

当你覆盖'漆();'请确保调用'super.paint(笔);'。 – Doorknob

回答

5

你的代码是完全的问题:

  1. 不要覆盖JFrame.paint(),特别是如果不调用super。设置一个ContentPane并覆盖它的paintComponent()。虽然看起来很方便,但它通常是一个糟糕的设计,也是不必要的。
  2. 不要覆盖JComponent.paint(),而是覆盖JComponent.paintComponent()(并调用super
  3. 使用JLabel来显示图像。它更简单。
  4. 请勿混合使用AWT(画布)和Swing(JFrame)。坚持摇摆。

下面是一个简单的例子,显示鲍瑟在框架周围移动。 (这很有趣,当你减少帧的大小和与框架边框;-)命中图像)

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.Random; 

import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestAnimation2 { 
    private static final int NB_OF_IMAGES_PER_SECOND = 50; 
    private static final int WIDTH = 800; 
    private static final int HEIGHT = 600; 
    private Random random = new Random(); 

    private double dx; 
    private double dy; 

    private double x = WIDTH/2; 
    private double y = HEIGHT/2; 

    protected void initUI() throws MalformedURLException { 
     final JFrame frame = new JFrame(TestAnimation2.class.getSimpleName()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLayout(null); 
     final JLabel label = new JLabel(new ImageIcon(new URL("http://www.lemondedemario.fr/images/dossier/bowser/bowser.png"))); 
     label.setSize(label.getPreferredSize()); 
     frame.setMinimumSize(label.getPreferredSize()); 
     frame.add(label); 
     frame.setSize(WIDTH, HEIGHT); 
     dx = getNextSpeed(); 
     dy = getNextSpeed(); 
     Timer t = new Timer(1000/NB_OF_IMAGES_PER_SECOND, new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       x += dx; 
       y += dy; 
       if (x + label.getWidth() > frame.getContentPane().getWidth()) { 
        x = frame.getContentPane().getWidth() - label.getWidth(); 
        dx = -getNextSpeed(); 
       } else if (x < 0) { 
        x = 0; 
        dx = getNextSpeed(); 
       } 
       if (y + label.getHeight() > frame.getContentPane().getHeight()) { 
        y = frame.getContentPane().getHeight() - label.getHeight(); 
        dy = -getNextSpeed(); 
       } else if (y < 0) { 
        y = 0; 
        dy = getNextSpeed(); 
       } 
       label.setLocation((int) x, (int) y); 

      } 
     }); 
     frame.setVisible(true); 
     t.start(); 
    } 

    private double getNextSpeed() { 
     return 2 * Math.PI * (0.5 + random.nextDouble()); 
    } 

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, 
      UnsupportedLookAndFeelException { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       try { 
        new TestAnimation2().initUI(); 
       } catch (MalformedURLException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 
}