Java Swing绘图(PaintComponent的问题)

时间:2014-05-12 17:39:56

标签: java image swing paintcomponent

这是我在这个论坛的第一篇文章,如果我在这里格式化或发布礼仪时出错,请提前原谅我。

我对Java Swing编程相当陌生,我一直试图为个人项目创建简单的塔防游戏,但是在我的应用程序中绘制图像时遇到了麻烦。我在这个论坛和甲骨文的许多java教程中都环顾四周,但我从来没有找到一个有助于解决这个问题的解决方案,所以我不得不求助于自己。 / p>

public static void main(String[] args) 
{
    new DotO();
}

public DotO()
{
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();             
        }
    });
}

private void createAndShowGUI()
{
    backgroundPanel = new JPanel();
    setBorder(BorderFactory.createLineBorder(Color.black));
    loadBackground();  
    setBackground(Color.white);  

    //1. Create the frame.
    JFrame frame = new JFrame("Defense Of The Origin");

    //2. Optional: What happens when the frame closes?
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //4. Size the frame.
    frame.setSize(SIZEX, SIZEY);

    //5. Show it.
    frame.setVisible(true);

    //3. Add Background Panel
    frame.add(backgroundPanel);  
}

private void loadBackground()  
{  
    String fileName = "resources/Background.jpg";  
    try  
    {  
        URL url = getClass().getResource(fileName);  
        backgroundImage = ImageIO.read(url);  
    }  
    catch(MalformedURLException mue)  
    {  
        System.out.println("url: " + mue.getMessage());  
    }  
    catch(IOException ioe)  
    {  
        System.out.println("read: " + ioe.getMessage());  
    }
}

@Override
protected void paintComponent(Graphics g)  
{  
    System.out.println("painted");
    super.paintComponent(g);  
    int w = getWidth();  
    int h = getHeight();
    g.drawImage(backgroundImage, 0, 0, w, h, this);  
    System.out.println("it's working");
}

框架确实打开,在首选尺寸上没有任何问题,但框架上没有任何内容。我只看到一个灰色空间,当我将一个System.out.print放在paintComponent方法中时,它不会在控制台中显示,所以我知道应用程序从未实际运行paintComponent方法。任何建议将不胜感激!

1 个答案:

答案 0 :(得分:2)

这显然属于一个类

class DotO extends JPanel { ... }

但是,在createAndShowGUI方法中,您正在创建面板并将此面板添加到框架中。在此面板中,不会覆盖paintComponent方法。

另一方面,你永远不会创造一个"可见" DotO的实例。您只是创建DotO的实例,但从不将其添加到框架中。

一种解决方案是省略backgroundPanel,而不是

frame.add(backgroundPanel);

你可以打电话

// Add "this" to the panel. "this" is the DotO instance
// where the `paintComponent` method is overridden
frame.add(this);

您应该考虑将GUI创建从DotO类中拉出来,并在main方法中创建框架,如下所示:

public static void main(String[] args) 
{
    SwingUtilities.invokeLater(new Runnable() 
    {
        public void run() 
        {
            createAndShowGUI();             
        }
    });
}

private static void createAndShowGUI() 
{
    //1. Create the frame.
    JFrame frame = new JFrame("Defense Of The Origin");

    //2. Optional: What happens when the frame closes?
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //4. Size the frame.
    frame.setSize(SIZEX, SIZEY);

    //5. Show it.
    frame.setVisible(true);

    // Here, create an instance of "DotO", and add it to the frame!
    frame.add(new DotO());
}

// In the DotO constructor, only do what has to be done
// specifically for this DotO instance:
public DotO()
{
    setBorder(BorderFactory.createLineBorder(Color.black));
    loadBackground();  
    setBackground(Color.white);  
}

但现在可以将其视为一个细节。


编辑回应评论:

为了绘制多个图像,您可以像背景图像一样加载和绘制它们(但背景图像之后,出于显而易见的原因)。

可以在这里提出许多进一步的建议。虽然严格来说,这不是问题+答案网站的目的,但应该通过阅读教程和代码示例来完成。

所以Q& A纯粹主义者:现在请离开,一些未回答的事情:


我知道Swing是一个很好的毒药":只需几行代码,你的第一帧就会有一些图像。但这并不意味着您在创建游戏时不必计划提前考虑。你不能只是编写更多代码"希望"一些不错的东西"会出来的。

因此,我建议您首先考虑游戏的结构应该如何。你会上哪节课?根据班级的字段方法,每个班级的责任应该是什么?

编写"测试片段"肯定没错。某些功能。例如,用于加载和显示背景图像的测试片段;-)但是,您无法通过从头开始将大量代码编写到单个类中来创建游戏。

此处的指南偶尔会在单词中描述 您想要实现的目标。作为一个例子(非常"压缩",以说明要点):

  

我想要一个具有一定范围的塔,可以拍摄并可以在屏幕上绘画

这可以帮助粗略派生一个结构:

  • 名词是班级
  • 形容词/属性是字段
  • 动词是方法

产生类似

的类
class Tower {
    float range;
    void shoot() {...}
    void paintInto(Graphics g) {...}
}

(这实际上只是一个非常粗略的准则!)

此外,还有许多细节需要考虑。例如,您随后会注意到将loadBackground()方法更改为类似

的方法可能会有所帮助
private void loadImage(String fileName)  
{  
    ...
}

可以被称为

的方法
background = loadImage("resources/Background.jpg");
tower = loadImage("resources/Tower.jpg");

但同样:这些是您可以从教程和代码示例中学到的东西(并且您希望(希望)迟早会自动执行)