本帖最后由 xxzblog 于 2012-12-12 23:19:11 编辑

解决方案 »

  1.   

    你这个代码能画出来,但是飞机移动时就出现了很多重叠的,因为上一次的绘图没有擦除。代码里面问题很多:第一,extends JFrame,然后直接重写它的 paint() 方法,是很不推荐的,最好是继承 JPanel 或者 JComponent,然后重写它的 paintComponent() 方法, offScrrenImage 也没有必要。第二,在构造方法中启动重绘线程,是错误的。构造方法中不要启动新线程,重绘线程也不要用普通的Thread或者Runnable,应该在构造方法之外,使用 javax.swing.Timer,然后定义一个 ActionListener,在 ActionListener 的 actionPerformed() 方法中调用重绘。第三,main方法直接写了 new HitAirplaneClient(); 是错误的。Swing的EDT法则说:任何Swing控件的初始化都应该在EDT中完成,Swing程序正确的main方法是使用 SwingUtilities.invokeLater(),或者用 EventQueue.invokeLater,前者内部调用后者。第四,固定频率调用 repaint() 是没有必要的,repaint() 可以在 move 的时候调用,FPS类游戏的“固定频率强制重绘”要求跟Swing的重绘机制有些冲突,很多写FPS类游戏的人都喜欢把Swing本身的重绘禁用,然后自己实现一个单线程的、双缓冲的FPS重绘机制,相当于自己实现一个满足FPS要求的“EDT”(但是用户输入捕获还是从EDT中获取),你这个小程序好像没有必要FPS。
      

  2.   

    代码更改:
    //主方法
    package com.xxz;import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;public class HitAirplaneClient extends JPanel {  //窗口的大小
      public static final int GAMEWIDTH = 800;
      public static final int GAMEHEIGHT = 600;
      
      private Airplane myAir;  public HitAirplaneClient() {    myAir = new Airplane(300, 500);
        //添加事件
        
        //设置窗口的大小
        setPreferredSize(new Dimension(GAMEWIDTH, GAMEHEIGHT));
      }  //画出窗口中的组件
      @Override
      public void paintComponent(Graphics g) {
        
        super.paintComponent(g); // JPanel默认为opaque,UI类会填充背景色
        
        myAir.draw(g);
      }  public static void main(String[] args) {
        
        SwingUtilities.invokeLater(new Runnable() {      @Override
          public void run() {
            
            JFrame f = new JFrame("HitAirplane——xxzkidQQ:727753098");
            HitAirplaneClient hac = new HitAirplaneClient();
            
            f.setContentPane(hac);
            f.pack();
            f.addKeyListener(hac.new KeyMonitor());
            //设置窗口不可变
            f.setResizable(false);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setLocationRelativeTo(null); // 在主屏幕居中
            f.setVisible(true);
          }
        });
      }  class KeyMonitor extends KeyAdapter {    @Override
        public void keyPressed(KeyEvent e) {
          
          myAir.move(e);
          repaint();
        }
      }
    }//飞机类
    class Airplane {  //飞机的宽度,高度
      private int airX, airY;
      private int YSpeed = 5;
      private int XSpeed = 5;  public Airplane(int airX, int airY) {
        this.airX = airX;
        this.airY = airY;
      }  public int getairX() {
        return airX;
      }  public void setairX(int airX) {
        this.airX = airX;
      }  public int getairY() {
        return airY;
      }  public void setairY(int airY) {
        this.airY = airY;
      }  //画出飞机
      public void draw(Graphics g) {
        Color c = g.getColor();
        g.setColor(Color.RED);
        g.drawRect(airX, airY, 10, 30);
        g.drawLine(airX, airY + 15, airX - 10, airY + 20);
        g.drawLine(airX + 10, airY + 15, airX + 20, airY + 20);
        g.setColor(c);
      }  public void move(KeyEvent e) {
        int key = e.getKeyCode();
        switch( key ) {
          case KeyEvent.VK_W: {
            airY -= YSpeed;
            break;
          }
          case KeyEvent.VK_S: {
            airY += YSpeed;
            break;
          }
          case KeyEvent.VK_A: {
            airX -= XSpeed;
            break;
          }
          case KeyEvent.VK_D: {
            airX += XSpeed;
            break;
          }
        }
      }
    }
    说句题外话,没有使用MVC感觉怪怪的。
      

  3.   

    我记得以前有个人专门发帖解释了一下
    直接使用paint(g)效果不好,好像是用compentPaint(g)才行。