无法在 JFrame 上绘画

Cant paint on JFrame

我在 JFrame 上绘制 JLabel 时遇到问题。我已经在另一个项目中这样做了,它工作正常,但这次我在某个地方搞砸了,不能再画了。这是我的代码:

董事会:

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

public class Board extends JPanel {

public Board() {
    initBoard();
}

private void initBoard() {
    setPreferredSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
    setMinimumSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
    setMaximumSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
    setBackground(Color.GRAY);
    setDoubleBuffered(true);
  }
}

帧数:

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.io.File;
import java.io.IOException;

public class Frame extends JFrame {

    public static final int GAME_WIDTH = 800;
    public static final int GAME_HEIGHT = 600;
    private final String title = "title here";

    private Image backgroundIMG;

    public Frame() {
        initUI();
    }

    private void initUI() {
        add(new Board());
        pack();
        setTitle(title);
        setSize(GAME_WIDTH, GAME_HEIGHT);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        setResizable(false);
        setLayout(null);


        /*
         * set background image
         */
        /*try {
            this.backgroundIMG = ImageIO.read(new File("src/to/image"));
        } catch (IOException e) {
            e.printStackTrace();
        }*/

        Border emptyBorder = BorderFactory.createEmptyBorder();

        int titleWidth = 270;
        int titleHeight = 55;
        int titleX = 24;
        int titleY = 30;
        int titleSize = 47;
        String titleFont = "Ravie";

        /*
         * Customize the startscreen
         */
        JLabel title = new JLabel("text");
        title.setBounds(0, 0, titleWidth, titleHeight);
        title.setFont(new Font(titleFont, Font.BOLD, titleSize));
        title.setForeground(new Color(251,102,8));
        title.setLocation(titleX, titleY);
        add(title);
        System.out.println("title should be printed");
    }
}

启动器:

import java.awt.*;

public class Launcher {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            Frame main = new Frame();
            main.setVisible(true);
        });
    }
}

当我启动程序时,框架正在加载但不显示 JLabel。它还在控制台上打印 "title should be printed" 。我已经做了一些研究,但找不到任何对我有帮助的东西。也许这只是一个微不足道的错误,有人可以很快帮助我。

提前致谢

暂时忽略所有 "interesting" 内容,您的基本问题归结为这个...

add(new Board());
//... 
add(title);

Java/Swing 以 LIFO 顺序绘制它的组件,所以最后添加的组件是第一个绘制的组件。

可能最合乎逻辑的解决方法是将 title 添加到 Board,但您可能想先解决几个其他问题...

  • 避免从顶级容器扩展,如 JFrame。有很多原因,但主要是,您没有向 class 添加新功能,而是将您锁定在一个可以通过其他 means/components
  • 更好地管理的用例中
  • 避免setPreferred/Minimum/MaximumSize。这些麻烦多于它们的价值。相反,根据需要覆盖 getPreferredSize
  • setDoubleBuffered(true); 毫无意义,因为 Swing 组件默认是双缓冲的
  • 避免 null 布局,严重的是,这是人们 post 关于 SO 的大多数问题的首要原因。布局管理 API 是有原因的,学会使用它。

如果我们将所有这些都考虑在内,您最终可能会更像是...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Image;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test {

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

    private final String title = "title here";

    public Test() {
        EventQueue.invokeLater(() -> {
            JFrame main = new JFrame(title);
            main.add(new MainPane());
            main.pack();
            main.setLocationRelativeTo(null);
            main.setVisible(true);
        });
    }

    public static final int GAME_WIDTH = 800;
    public static final int GAME_HEIGHT = 600;

    public static class MainPane extends JPanel {

        private Image backgroundIMG;

        public MainPane() {
            setLayout(new BorderLayout());

            setBackground(Color.GRAY);

            add(new Board());

            String titleFont = "Ravie";
            int titleSize = 47;
            JLabel title = new JLabel("text");
            title.setHorizontalAlignment(JLabel.CENTER);
            title.setFont(new Font(titleFont, Font.BOLD, titleSize));
            title.setForeground(new Color(251, 102, 8));
            add(title, BorderLayout.NORTH);
        }
    }

    public static class Board extends JPanel {

        public Board() {
            initBoard();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(GAME_WIDTH, GAME_HEIGHT);
        }

        private void initBoard() {
            setBackground(Color.GRAY);
        }
    }

}