将JApplet嵌入JFrame

3

好的,我想知道有没有人能告诉我哪里出了问题。

我有一个名为Game的JApplet,如果我使用AppletViewer从eclipse中运行它并拥有一个名为GUI的JFrame来容纳JApplet,则可以正常运行。以下是两者的代码:

PS. 我删除了Game中的大部分代码,以使其更小,现在只是基本的。

Game.java:

package com.ion.brickdodge;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;

import javax.swing.JApplet;


public class Game extends JApplet implements Runnable{

private static final long serialVersionUID = 1L;
Image man1;
Image man2;
Image cman; 
int WIDTH = 250;
int HEIGHT = 350;
int lives = 3;
int spx = WIDTH / 2;
int score = 0;

Image dbImage;
Graphics dbg;

public void init () {
    setSize  (WIDTH, HEIGHT);
    setFocusable(true);
    setBackground(Color.LIGHT_GRAY);

    man1 = getImage(getCodeBase(), "res/man1.png");
    man2 = getImage(getCodeBase(), "res/man2.png");

    cman = man1;

}

public void start() {
    Thread th = new Thread(this);
    th.start();
}

public void run() {
    Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
    while(true){
        repaint();

        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    }   
}

public void paint(Graphics g) {

    g.drawImage(cman, spx, 320, this);
    g.setColor(Color.BLACK);
    g.drawString("Score: " + score, 5, 10);
    g.drawString("Lives: " + lives, 5, 25);

}

public void update(Graphics g){
    if (dbImage == null)
    {
        dbImage = createImage (this.getSize().width, this.getSize().height);
        dbg = dbImage.getGraphics ();
    }

    dbg.setColor (getBackground ());
    dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);

    dbg.setColor (getForeground());
    paint (dbg);

    g.drawImage (dbImage, 0, 0, this);
}
    }

这里是GUI.java文件:

package com.ion.brickdodge;

import java.awt.BorderLayout;

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


public class GUI {

public static void main(String args[]) {
      JFrame frame = new JFrame("test");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(1000, 1000);

      JPanel panel = new JPanel(new BorderLayout());
      frame.add(panel);

      JApplet applet = new Game();
      panel.add(applet, BorderLayout.CENTER);
      applet.init();
      frame.pack();

      frame.setVisible(true);
    }
}

当我运行Error GUI.java时,它会抛出错误...

Exception in thread "main" java.lang.NullPointerException
at java.applet.Applet.getCodeBase(Unknown Source)
at com.ion.brickdodge.Game.init(Game.java:30)
at com.ion.brickdodge.GUI.main(GUI.java:22)

任何帮助都将不胜感激。

你为什么要这样做呢?为什么不让你的类创建一个JPanel,然后根据需要将其放入JApplet或JFrame中,以便根据需要将其用作应用程序或桌面? - Hovercraft Full Of Eels
你的NPE可能是由man1 = getImage(getCodeBase(), "res/man1.png");生成的。 - Kazekage Gaara
图像文件是否与小程序本身在同一目录中? - fireshadow52
注意:可以使用JWS启动自由浮动的小程序。但最好先在面板中编写游戏并将其放入框架中,然后使用JWS启动它。 - Andrew Thompson
2个回答

3
我会把这个问题变成一个答案:我认为更好的解决方案是将你的GUI设计为创建JPanels。然后,如果你想将GUI作为applet运行,只需创建你的JPanel并将其放置在JApplet的contentPane中。同样,如果你想创建一个JFrame,那么创建你的JPanel并将其放置在JFrame的contentPane中。
其他问题:
考虑将图像作为资源获取,因为它们很可能会保存在jar文件中。 不要直接在顶级窗口(如JApplet)中绘制,也不要使用paint方法。 相反,在JPanel的重写的paintComponent(...)方法中进行绘制。这将使您的代码能够利用Swing的双缓冲技术。 不要在Swing GUI中覆盖update(...)。这适用于AWT,但应避免在Swing中使用。 不要在绘图方法中读取任何图像或执行任何其他CPU密集型操作。 查看Swing绘图教程,了解应该如何编写此类代码。您可以在这里找到入门教程here,以及更高级的文章here

好的,我还有点困惑。这个游戏是一个Applet,因为它需要在网页中运行,但是我需要为这个特定的游戏制作一个独立的应用程序。我以为我可以将它改成JApplet并将其包含在JFrame中,但这不可能吗? - Lucas_F98
可以实现,但有些麻烦。你仍需要创建一个带有paintComponent(...)覆盖的JPanel或JComponent来进行绘制。你是否已经学习了Swing图形教程(考虑到你的代码,我认为你还没有)。在继续进行这个项目之前,建议先学习一下。 - Hovercraft Full Of Eels
@Lucas:很好,但还是看看我提供的链接。你不会后悔阅读它们,尤其是第二个链接。 - Hovercraft Full Of Eels
是的,我有,它们是非常好的教程,这就是我学习用Java制作游戏的方式。 - Lucas_F98

3
注意:如果问题是“为什么会发生这种情况?”,答案是JVM会自动设置小程序上下文和存根。但是,除非小程序被加载在网页中,否则不会发生。如果您正在自行加载它,则需要实现、实例化和附加这些功能。
一旦您拥有通常由小程序元素提供的细节,做到这一点并不难。
(另一方面,最好的策略是将游戏转换为面板,将其放入框架中,并使用JWS启动它。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接