使用Graphics2D绘制图像

时间:2012-11-16 22:15:15

标签: java swing graphics graphics2d

我正在尝试使用java的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);
        }
    }

}

传递给Tester的Component对象是以下类:

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);
    }

我确保这个类只有一个我添加的精灵。精灵类大致如下:

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);
    }

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

1 个答案:

答案 0 :(得分:5)

您的代码充满了问题:

  1. 请勿覆盖JFrame.paint(),尤其是在不调用super的情况下。设置ContentPane并覆盖其paintComponent()。虽然看起来很方便,但它通常是一个糟糕的设计而且没必要。
  2. 不要覆盖JComponent.paint(),而是覆盖JComponent.paintComponent()(并调用super
  3. 使用JLabel显示图像。它简单得多。
  4. 不要混合使用AWT(Canvas)和Swing(JFrame)。坚持摇摆。
  5. 这是一个简单的例子,显示了一个围绕框架移动的Bowser。 (当你减小框架尺寸并使用框架边框点击图像时很有趣; - ))

    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();
                    }
                }
            });
        }
    }