如何在JFrame上显示带有图像的两个JPanel,并且两个img都可见?

时间:2018-09-11 18:44:00

标签: java swing jframe jpanel

我正在尝试将水族馆(这是扩展JPanel并包含水族馆img的类)和顶部的鱼(这也是扩展JPanel的类)设置为背景并包含鱼的img)。

问题在于,它在水族馆顶部仅显示一个图像,而不是鱼类(水族馆或鱼类,具体取决于首先添加到JFrame中的哪个)。

主要

public class Core {
    JFrame window;
    JLabel label;
    ImageIcon img;      
    Aquarium aquarium = new Aquarium();
    JavaFish javaFish = new JavaFish();

    public void start() {
        window = new JFrame();
        window.setPreferredSize(new Dimension(600, 400));
        window.setVisible(true);
        window.setTitle("Java Game");
        aquarium.add(javaFish);
        window.add(aquarium);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        Core c = new Core();
        c.start();
    }
}

水族馆

public class Aquarium extends JPanel {

    private BufferedImage img;
    //Initiate aquarium width 
    public int width;
    //Initiate aquarium height
    public int height;

    @Override
    protected void paintComponent(Graphics g) {
        width = getSize().width;
        height = getSize().height;

        try {
            img = ImageIO.read(new File("img/AquariumBackground.png"));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Image not fount!");
        }

        g.drawImage(img, 0, 0, width, height, this);
    }               
}

public class JavaFish extends JPanel {
    BufferedImage img;
    int xPos = 50;
    int yPos = 50;

    public JavaFish() {
        this.setOpaque(false);
    }

    @Override
    protected void paintComponent(Graphics g) {
        BufferedImage JavaFish = LoadImage("img/JavaFish.png");
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(JavaFish, xPos, yPos, 100, 100, null);
        repaint();
    }

    BufferedImage LoadImage(String FileName) {
        img = null;
        try {
            img = ImageIO.read(new File (FileName));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return img;
    }
}

1 个答案:

答案 0 :(得分:1)

  

问题在于,它仅显示一个图像,而不是在水族馆顶部显示鱼(水族馆或鱼,具体取决于首先将哪个图像添加到JFrame)。

默认情况下,JPanel使用FlowLayout时要遵守添加到其中的任何组件的首选大小。

默认情况下,JFrame使用BorderLayout,如果您未指定约束,则组件会添加到CENTER的{​​{1}}中,这意味着该组件会自动调整大小以填充框架的空间。

因此,添加到框架的组件的大小将被设置为可填充框架。添加到面板的组件的大小为(0,0),因此无需绘制任何内容。

一些自定义绘画技巧:

  1. 重写面板的BorderLayout方法以返回图像的大小,以便布局管理器可以完成其工作

  2. 调用super.paintComponent(..)作为确保清除背景的第一条语句。

  3. 不要在paintComponent()方法中读取图像。每当Swing确定需要重新粉刷组件时都可以调用此方法,因此继续读取图像效率不高。相反,应该在类的构造函数中读取图像。

  4. 不要在绘画方法中调用repaint()。这将导致无限的绘画循环。

此外,在使框架可见之前,应将组件添加到框架中。

如上所述,Alerra在评论中建议在同一面板上绘制两个图像是一个好主意。它可以简化绘制过程,甚至可以通过保留要绘制的图像的ArrayList来轻松绘制多条鱼。然后,您只需绘制背景,然后遍历ArrayList即可绘制单个鱼。

查看Custom Painting Approaches以获取有效示例。该示例仅绘制Rectangle,但是概念相同。