如果我使用 paintComponent,我该如何显示 JLabel?

If I use paintComponent, how do I show a JLabel?

我是 Java 的新手,我正在制作一款游戏,您可以在其中上下冲刺以避开障碍物。我几乎完成了所有主要功能,还得做评分系统和背景。考虑到分数会更容易,我写了一个 JLabel 并将其添加到我的 JFrame 中。它一闪就消失了。我相当确定这是因为我在之后直接添加了整个图形方法,或者类似的东西。但是,如果我在之后添加 JLabel,那就是所有添加的内容,它会占据整个屏幕。

package dash;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main extends JPanel implements ActionListener {//ignore yellow line
//setting up class
    Variables var = new Variables();
    Timer timer = new Timer(5,this);
    boolean spacePressed;
    boolean gameActive = false;
    boolean creatingObstacles = true;
    int arrayLength;
    int creationStep = 50;
    int backgroundx;
    int speed = 30;
    int x;
    int y;
    int playery = 700;
    int highscore;
    int score = 1;
    static int[] obstacles = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//making label
    JLabel label = new JLabel("score: " + score);
//setting up graphics method
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
//player
        ImageIcon player = new ImageIcon("C:\Users\myname\Documents\Eclipse Projects\dash\player.png");
        player.paintIcon(this,g,300,playery);
//label properties
        label.setBounds(300,900,100,100);
//Some really cool code that took a while to write, this is going to generate random obstacles so I don't
//have to make all the levels since I'm lazy. This also makes graphics easier, since now I don't have
//to draw out the map taking up a lot of memory, at least several gigs probably more, for small levels. 
        int min = 500;
        int max = 1500;
        arrayLength = obstacles.length - 1;
//creating random array, im really proud of this
//code. it took me hours to write and looks badass
//except i have no clue how to label anything now T-T
        while (creationStep > 0) {
            if (creatingObstacles == true) {
                obstacles[arrayLength] = (int)Math.floor(Math.random()*(max-min+1)+min) + var.previousNumber;
                var.previousNumber = obstacles[arrayLength];
                arrayLength--;
                creationStep--;
                if (arrayLength == -1) {
                    creatingObstacles = false;
                    arrayLength = obstacles.length - 1;
                }}}
//drawing with the array
//ps i have no clue why this works, but it does
        boolean onTop = true;
        
        while (arrayLength >= 0) {
//drawing obstacles
            ImageIcon obstacle = new ImageIcon("C:\Users\myname\Documents\Eclipse Projects\dash\obstacle.png");
            obstacle.paintIcon(this,g,obstacles[arrayLength] + backgroundx,y);
//checking collision
            if (obstacles[arrayLength] + backgroundx >= 300 && obstacles[arrayLength] + backgroundx <= 400 && y == playery) {
                spacePressed = false;
                gameActive = false;
                backgroundx = 0;
            }
//finishing loop
            arrayLength--;
//deciding if it puts the obstacle on top or bottom
            if (onTop) {
                y = 200;
            } else {
                y = 700;
            }
//toggling onTop boolean
            onTop = !onTop;
        }
//when to make a new array
        if (obstacles[0] <= -backgroundx) {
            var.previousNumber = -backgroundx + 2000;
            creationStep = 50;
            creatingObstacles = true;
            speed = speed + 5;
        }
//pause
        if (gameActive == false) {
            ImageIcon pauseScreen = new ImageIcon("C:\Users\myname\Documents\Eclipse Projects\dash\pausescreen.png");
            pauseScreen.paintIcon(this,g,0,0);
        }
//timer, this starts physics
        timer.start();
    }
//setting up keys
    KeyListener key = new KeyListener() {
        @Override
        public void keyTyped(KeyEvent e) {
            if(e.getKeyChar() == KeyEvent.VK_ESCAPE) {
                gameActive = !gameActive;
            }
        }
        @Override
        public void keyPressed(KeyEvent e) {
            if(e.getKeyChar() == KeyEvent.VK_SPACE && gameActive == true) {
                spacePressed = !spacePressed;
            }
        }
        @Override
        public void keyReleased(KeyEvent e) {
        }
    };
//physics go here
    public void actionPerformed(ActionEvent e) {
        if (spacePressed == true) {
            playery = 200;
        } else {
            playery = 700;
        }
//movement
        if (gameActive == true) {
            backgroundx = backgroundx - speed;
        }
        repaint();
        }   
//main method
    public static void main(String[] args) {
//implementing method
        Main main = new Main();
//creating frame
        JFrame frame = new JFrame();
        frame.setFocusable(true);
        frame.setSize(1920,1080);
        frame.setVisible(true);
        frame.addKeyListener(main.key);
        frame.add(main.label);
        frame.add(main);
    }
}
class Variables{
    int previousNumber;
}
    frame.add(main.label);
    frame.add(main);

框架的默认布局管理器是 BorderLayout。

您不能将两个组件添加到 BorderLayout 的“CENTER”,如果您没有指定约束,这是默认设置。

尝试以下操作以查看差异:

    frame.add(main.label, BorderLayout.PAGE_START);
    frame.add(main, BorderLayout.CENTER);

阅读有关 Layout Manager 的 Swing 教程部分,了解有关 BorderLayout 和其他布局管理器如何工作的更多信息。