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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在JFrame上显示带有图像的两个JPanel,并且两个img都可见?相关的知识,希望对你有一定的参考价值。

我试图将水族馆(这是一个延伸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;
    }
}
答案

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

默认情况下,JPanel使用FlowLayout,它尊重添加到其中的任何组件的首选大小。

默认情况下,JFrame使用BorderLayout,如果没有指定约束,则组件会添加到CENTERBorderLayout中,这意味着组件会自动调整大小以填充框架的空间。

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

所以一些自定义绘画技巧:

  1. 覆盖面板的getPreferredSize()方法以返回图像的大小,以便布局管理器可以完成其工作
  2. 调用super.paintComponent(..)作为第一个语句,以确保清除背景。
  3. 不要在paintComponent()方法中读取图像。只要Swing确定需要重新绘制组件,就可以调用此方法,因此不能有效地继续读取图像。相反,应该在类的构造函数中读取图像。
  4. 不要在绘画方法中调用repaint()。这将导致无限的绘画循环。

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

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

查看Custom Painting Approaches的工作示例。该示例仅绘制Rectangle,但概念是相同的。

以上是关于如何在JFrame上显示带有图像的两个JPanel,并且两个img都可见?的主要内容,如果未能解决你的问题,请参考以下文章

在 JFrame 中将图像绘制到 JPanel

JPanel 在调整 Jframe 大小之前不会更新

图像未显示在 jPanel 中

Java:保持JPanel背景图像的纵横比

使用框架状态变量更新 JFrame 中的 JPanel 内容

在 JFrame 上更改 JPanel 组件时无法显示它