为什么我的内容窗格不会显示在我的JFrame上?

时间:2013-12-19 01:10:10

标签: java swing jframe jpanel

这是我的图形类,但是当我创建并添加JPanel作为内容窗格时,没有任何内容显示出来。我做了很多测试,看看我的内容窗格是否可见,但仍然无法显示。

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionListener;

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


public class GraphicsMain extends JFrame{
    public static final long serialVersionUID = 7610350056926018727L;
    static GraphicsMain frame = new GraphicsMain();
    static final int WIDTH = 1024, HEIGHT = 768;
    static Listener listener = new Listener();

    public static void init() {
        createGUI();
    }

    public static void createGUI() {
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.setFocusable(true);
        frame.setLayout(null);
        frame.setResizable(false);
        frame.setSize(WIDTH, HEIGHT);
        frame.setTitle("Game of Life");
        frame.setContentPane(frame.createMainPanel());
        frame.setVisible(true);
    }

    public JPanel createMainPanel() {
        JPanel totalGUI = new JPanel();
        totalGUI.setSize(HEIGHT, WIDTH);
        totalGUI.setBackground(Color.red);
        totalGUI.setLayout(null);

        JPanel buttonPanel = createButtonPanel();

        totalGUI.add(buttonPanel);
        totalGUI.setVisible(true);
        System.out.println("Is returning!");
        return totalGUI;
    }

    public JPanel createButtonPanel() {
        JPanel buttonPanel = new JPanel();
        buttonPanel.setSize(WIDTH, HEIGHT);
        buttonPanel.setLocation(0, 0);

        Font buttonFont = new Font("Button Font", Font.PLAIN, 12);
        JButton goButton = createButton("Go", WIDTH/16, HEIGHT/12, 10, 10, listener, buttonFont, Color.black);
        buttonPanel.add(goButton);
        JButton clearButton = createButton("Clear", WIDTH/16, HEIGHT/12, 10 + HEIGHT/12, 10, listener, buttonFont, Color.black);
        buttonPanel.add(clearButton);
        JButton exitButton = createButton("Exit", WIDTH/16, HEIGHT/12, 10 + 2*HEIGHT/12, 10, listener, buttonFont, Color.black);
        buttonPanel.add(exitButton);
        return buttonPanel;
    }

    public JButton createButton(String text, int width, int height, int x, int y, ActionListener listener, Font font, Color color) {
        JButton button = new JButton(text);
        button.setSize(width, height);
        button.setLocation(x, y);
        button.addActionListener(listener);
        button.setFont(font);
        button.setForeground(Color.red);
        return button;
    }

}

这个类由

调用
import javax.swing.SwingUtilities;


public class GameOfLifeMain {
    static boolean running = true;
    static int UPS = 60;
    static GameOfLifeMain main = new GameOfLifeMain();

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                main.init();
                long startTime = System.nanoTime();
                double ns = 1000000000.0 / UPS;
                double delta = 0;

                long secondTimer = System.nanoTime();
                while(running) {
                    long now = System.nanoTime();
                    delta += (now - startTime) / ns;
                    startTime = now;
                    while(delta >= 1) {
                    main.update();
                        delta--;
                    }
                    main.render();

                    if(System.nanoTime() - secondTimer > 1000000000) {
                        secondTimer += 1000000000;
                    }
                }
            }
        });
    }

    public void init() {
        GraphicsMain.init();
    }

    public void update() {
    }

    public void render() {
        //GraphicsMain.render();
    }

}

2 个答案:

答案 0 :(得分:2)

你的问题(至少)有两个问题:

  • 正如@Radiodef精明地指出的那样,你正在Swing事件线程上调用一个长时间运行的循环。由于该线程完全负责GUI的呈现以及与用户的交互,因此GUI完全被冻结。
  • 您正在使用空布局,这使您完全负责使用组件添加到空布局的所有组件的位置和大小。

我建议:

  • 正如@Radiodef建议的那样,在后台线程(如SwingWorker)中执行长时间运行的循环。这样可以更轻松地在GUI和后台进程之间进行交互。他的链接很好:Concurrency in Swing
  • 使用嵌套的JPanel,每个都使用自己的布局来实现所需的布局,一个可以在任何平台和任何视频卡设置上运行良好的布局。
  • 最好覆盖您的绘图JPanels getPreferredSize(...)方法,使其大小正确。
  • 通过setOpaque(true)将JPanel设置为不透明将无济于事,因为默认情况下JPanels已经是不透明的。

修改
我对Jan Bodnar的最后一点进行了纠正:

  

“但是,大多数标准JComponent子类(例如JButton和JTree)上此属性的默认值依赖于外观。”例如,默认情况下,GTK外观的JPanel不是不透明的。

谢谢,Jan

答案 1 :(得分:0)

在面板上调用setOpaque(true),然后将绘制背景。我还注意到在定义面板大小时混淆了WIDTH和HEIGHT(这可能是一个错误)。