我可以将 JPanel 添加到已经带有图形的 JFrame 中吗?

Can i add JPanels to a JFrame with Graphics already on it?

所以我最近开始研究 java 图形,但遇到了一个问题。我已经将图像绘制到 JFrame 上,但没有了解到如果图像都在一个 JFrame 中,则图像的边界不能相互重叠(在另一个图像所在的位置设置边界会使图像消失)。我听说过使用多个 JPanel 来解决这个问题。我不知道如何执行此操作,因为我在我的程序中使用了 JFrame 而不是 JPanel,因此在此问题上提供一些帮助将不胜感激。谢谢,如果这个问题很愚蠢,我深表歉意。 (我的另一个问题,其他人似乎认为与这个问题相同,是设置界限的问题,这个问题是关于界限重叠和相互覆盖的问题) 这是我的 类:

WindowClass-

package game.thirdTry;

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

public class Window extends JFrame {

    private static Window instance;
    public static Window getInstance() {
        if(instance == null) {
            instance = new Window("Game");
        }
        return instance;
    }
    private Window(String name) {
        super(name);
        setSize(1200, 700);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(null);
        //setUndecorated(true);
        addKeyListener(new UserInput());
        //this.getContentPane().getSize();

        WindowStructure banner = new WindowStructure("Beatles Logo.jpg", 0, 0, getWidth(), 75);
        //WindowStructure fball = new WindowStructure("fireball.100x100.png", 100, 100, 100, 100);

        WindowStructure fball = WindowStructure.getInstanceF();

        System.out.println("Fball.xSize: " + fball.xSize + ", Fball.ySize: " + fball.ySize);
        System.out.println("Fball.xLoc: " + fball.xLoc + ", Fball.yLoc: " + fball.yLoc);
        //banner.setBounds(banner.xLoc, banner.yLoc, banner.xSize, banner.ySize);
        //fball.setBounds(fball.xLoc, fball.yLoc, fball.xLoc + fball.xSize, fball.ySize + fball.ySize);
        banner.setBounds(0, 0, getWidth(), getHeight());
        fball.setBounds(0, 75, getWidth(), getHeight());
        add(fball, null);
        add(banner, null);

        setVisible(true);

        while(true){
            System.out.println("Fball.xLoc: " + fball.xLoc + ", Fball.yLoc: " + fball.yLoc);
            repaint();
            try{
            Thread.sleep(10);
            }catch (Exception e){

            }
        }
    }
/*
    public void paint(Graphics g) {
        super.paintComponents(g);
    }
*/
}

图片Class-

package game.thirdTry;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class WindowStructure extends JPanel {

    private static WindowStructure fball;

    public static WindowStructure getInstanceF(){
        if(fball == null){
            fball = new WindowStructure("fireball.100x100.png", 0, 75, 100, 100);
        }
        return fball;
    }
    ImageIcon imageIcon;
    int xLoc, yLoc, xSize, ySize;

    public WindowStructure(String bannerImg, int xLoc, int yLoc, int xSize, int ySize){
        URL bannerImgURL = getClass().getResource(bannerImg);
        imageIcon = new ImageIcon(bannerImgURL);
        this.xLoc = xLoc;
        this.yLoc = yLoc;
        this.xSize = xSize;
        this.ySize = ySize;
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(imageIcon.getImage(), xLoc, yLoc, xSize, ySize, null);
    }
}

KeyListener/用户输入Class-

package game.thirdTry;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class UserInput implements KeyListener {
    // Window window = Window.getInstance();
    WindowStructure fball = WindowStructure.getInstanceF();

    boolean goUp = false;
    boolean goDown = false;
    boolean goLeft = false;
    boolean goRight = false;

    public void moveUpDown() {
        if (goUp && goDown) {
            if (fball.yLoc > 0) {
                fball.yLoc -= 10;
            }
        } else if (goUp) {
            if (fball.yLoc > -5) {
                fball.yLoc -= 10;
            }
        } else if (goDown) {
            if (fball.yLoc < 480) {
                fball.yLoc += 10;
            }
        }
        System.out.println("moveUpDown() method called");
    }

    public void moveLeftRight() {
        if (goLeft && goRight) {
            if (fball.xLoc < 1100) {
                fball.xLoc += 10;
            }
        } else if (goRight) {
            if (fball.xLoc < 1110) {
                fball.xLoc += 10;
            }
        } else if (goLeft) {
            if (fball.xLoc > 0) {
                fball.xLoc -= 10;
            }
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W) {
            goUp = true;
            goDown = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_S) {
            goDown = true;
            goUp = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_A) {
            goLeft = true;
            goRight = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_D) {
            goRight = true;
            goLeft = false;
        }
        moveUpDown();
        moveLeftRight();
        System.out.println("keyPressed() was called");
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W) {
            goUp = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_S) {
            goDown = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_A) {
            goLeft = false;
        }
        if (e.getKeyCode() == KeyEvent.VK_D) {
            goRight = false;
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

}
//g2d.drawImage(imageIcon.getImage(), xLoc, yLoc, xSize, ySize, null);

问题是您在绘制图像时正在缩放图像。因此,图像占据了整个 window space,所以是的,它绘制在首先绘制的图像之上。

只需按实际大小绘制图像:

g2d.drawImage(imageIcon.getImage(), xLoc, yLoc,  this);

这是使用 JLabel 的另一个原因。您无需担心尺寸。您只需将标签放在特定位置,图像就会被绘制出来。代码要简单得多。使用这种方法,您无需担心使面板不透明。

您的代码现在的问题是您需要使面板变大,因为您正在绘制相对于 WindowStructure 面板的图像。所以如果你的图像是 (25 x 25) 并且你想要在 (100, 100) 绘制图像,你需要制作面板 (125, 125),这意味着面板需要是透明的,所以面板的一部分不包含图像未绘制。使用 JLable,标签的大小将始终为 (25, 25),因此您可以简单地设置标签的位置,并且只会绘制 (25, 25) 个像素。

I'll look more into JLabels later

现在看看。没有比现在更好的时间了!

此外,您的 WindowStructure class 的设计很糟糕。不需要静态方法和变量。每张图片应该相互独立。