我试图了解JFrame和JPanel之间的区别。我倾向于使用JFrame的子类而不是JPanel,但是人们总是告诉我,最好使用JPanel的子类。这是我使用JFrame的示例:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;

public class Game extends JFrame implements Runnable {
int x, y, xCoord, yCoord;
private Image dbImage;
private Graphics dbg;

public void move() {
    x += xCoord;
    y += yCoord;
    if (x <= 20) {
        x = 20;
    }
    if (x >= 480) {
        x = 480;
    }
    if (y <= 40) {
        y = 40;
    }
    if (y >= 480) {
        y = 480;
    }
}

public void setXCoord(int xcoord) {
    xCoord = xcoord;
}

public void setYCoord(int ycoord) {
    yCoord = ycoord;
}

public class AL extends KeyAdapter {

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == e.VK_LEFT) {
            setXCoord(-1);
        }
        if (keyCode == e.VK_RIGHT) {
            setXCoord(+1);
        }
        if (keyCode == e.VK_UP) {
            setYCoord(-1);
        }
        if (keyCode == e.VK_DOWN) {
            setYCoord(+1);
        }
        Game.this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == e.VK_LEFT) {
            setXCoord(0);
        }
        if (keyCode == e.VK_RIGHT) {
            setXCoord(0);
        }
        if (keyCode == e.VK_UP) {
            setYCoord(0);
        }
        if (keyCode == e.VK_DOWN) {
            setYCoord(0);
        }
        Game.this.repaint();

    }

}

public static void main(String[] args) {
    Game game = new Game();
    Thread t = new Thread(game);
    t.start();
}

public Game() {
    addKeyListener(new AL());
    setTitle("Game");
    setSize(500, 500);
    setResizable(true);
    setVisible(true);
    setBackground(Color.BLACK);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    x = 250;
    y = 250;

}

public void paintComponent(Graphics g) {
    g.setColor(Color.GREEN);
    g.fillOval(x, y, 15, 15);
}

@Override
public void paint(Graphics g) {
    dbImage = createImage(getWidth(), getHeight());
    dbg = dbImage.getGraphics();
    paintComponent(dbg);
    g.drawImage(dbImage, 0, 0, this);
}

@Override
public void run() {
    try {
        while (true) {
            move();
            Thread.sleep(30);
        }
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
}

}


这样做很好(除了按住一个按钮时会有一点延迟),但是当我尝试通过实现JPanel而不是JFrame来更改代码时,什么都没有显示出来。这是JPanel子类的代码:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Game extends JPanel implements Runnable {
int x, y, xCoord, yCoord;
private Image dbImage;
private Graphics dbg;
JFrame frame;

public void move() {
    x += xCoord;
    y += yCoord;
    if (x <= 20) {
        x = 20;
    }
    if (x >= 480) {
        x = 480;
    }
    if (y <= 40) {
        y = 40;
    }
    if (y >= 480) {
        y = 480;
    }
}

public void setXCoord(int xcoord) {
    xCoord = xcoord;
}

public void setYCoord(int ycoord) {
    yCoord = ycoord;
}

public class AL extends KeyAdapter {

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == e.VK_LEFT) {
            setXCoord(-1);
        }
        if (keyCode == e.VK_RIGHT) {
            setXCoord(+1);
        }
        if (keyCode == e.VK_UP) {
            setYCoord(-1);
        }
        if (keyCode == e.VK_DOWN) {
            setYCoord(+1);
        }
        Game.this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == e.VK_LEFT) {
            setXCoord(0);
        }
        if (keyCode == e.VK_RIGHT) {
            setXCoord(0);
        }
        if (keyCode == e.VK_UP) {
            setYCoord(0);
        }
        if (keyCode == e.VK_DOWN) {
            setYCoord(0);
        }
        Game.this.repaint();

    }

}

public static void main(String[] args) {
    Game game = new Game();
    Thread t = new Thread(game);
    t.start();
}

public Game() {
    frame = new JFrame();
    frame.addKeyListener(new AL());
    frame.setTitle("Game");
    frame.setSize(500, 500);
    frame.setResizable(true);
    frame.setVisible(true);
    frame.setBackground(Color.BLACK);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    x = 250;
    y = 250;

}

@Override
public void paintComponent(Graphics g) {
    g.setColor(Color.GREEN);
    g.fillOval(x, y, 15, 15);
}

@Override
public void paint(Graphics g) {
    dbImage = createImage(getWidth(), getHeight());
    dbg = dbImage.getGraphics();
    paintComponent(dbg);
    g.drawImage(dbImage, 0, 0, this);
}

@Override
public void run() {
    try {
        while (true) {
            move();
            Thread.sleep(30);
        }
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
}

}

最佳答案

如代码所示,您需要自定义JPanel,因为您想更改某些方法的行为,例如paintComponent

但是,您不需要自定义JFrame,因此无需创建扩展它的类。

最后,您的主班不必成为小组班。

这是一个示例类,我将框架内容从Game的构造函数移到了这个主类。

 public class MainClass {

    public static void main(String[] args) {

    Game game = new Game();

    JFrame frame = new JFrame();

    frame.addKeyListener(new AL());
    frame.setTitle("Game");
    frame.setSize(500, 500);
    frame.setResizable(true);
    frame.getContentPane().add(game);
    frame.setBackground(Color.BLACK);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    Thread t = new Thread(game);
    t.start();

    }


    }

09-30 15:49
查看更多