外部JPanel类在Main JFrame类中无法正确显示

时间:2017-08-21 18:32:39

标签: java swing java-threads

基本上我试图理解Java中的Threads。所以我想我创建一个包含来自外部类的两个JPanel的主JFrame类,然后在一个中执行某些操作并使用来自第二个面板的消息来控制它到目前为止,我只创建了第一个外部面板,问题开始了!虽然看起来像是#34;已加载"但它没有正确显示。(参见system.out行) 所以这是主类

package com.maybee.gui;

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

public class Maybee extends JFrame implements Runnable 
{
public JFrame  maynFrame = null;
public JPanel contentPanel = null;
public SimPanel simPanel = null;

public int screenWidth = 0;
public int screenHeight = 0;

public Maybee()
{

}


private void init()
{
    System.out.println("In Inint");
    maynFrame = new JFrame("Maybee");
    maynFrame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
    screenWidth = gd.getDisplayMode().getWidth();
    screenHeight = gd.getDisplayMode().getHeight();
    maynFrame.setPreferredSize(new Dimension(screenWidth,screenHeight - 100));
    maynFrame.setContentPane(getContentPanel());
    maynFrame.setVisible(true);
    maynFrame.pack();
}

public JPanel getContentPanel()
{
    if (contentPanel == null)
    {
        contentPanel = new JPanel();
        contentPanel.setPreferredSize(new Dimension(screenWidth,screenHeight - 100));
        contentPanel.setBorder(new LineBorder(Color.BLUE));
        contentPanel.setBackground(Color.RED);
        contentPanel.setLayout(new BorderLayout());
        contentPanel.add(getSimPanel(),BorderLayout.CENTER);

    }

    return contentPanel;
}

public SimPanel getSimPanel()
{
    if(simPanel == null)
    {
        simPanel = new SimPanel(this);

    }
    return simPanel;
}


public static void main(String[] args)
{

    EventQueue.invokeLater(new Runnable() 
    {
        public void run()
        {
            System.out.println("Start");
            Maybee maybee =  new Maybee();
            maybee.run();

        }

    });
}

public void run()
{
    init();

}

}

现在是第一个外部JPanel类

package com.maybee.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class SimPanel extends JPanel
{
   public Maybee localMaybee = null;
   public JPanel simPanel = null;
   private JButton btn;

   public SimPanel(Maybee interMaybee)
  {
    localMaybee = interMaybee;
    init();
  }

  public void init()
  {
    simPanel = new JPanel();
    simPanel.setLayout(new BorderLayout());
    simPanel.setPreferredSize(new Dimension(localMaybee.screenWidth/4,localMaybee.screenHeight - 100));
    simPanel.setBackground(Color.GREEN);
    simPanel.add(getBtn(),BorderLayout.CENTER);
    simPanel.setVisible(true);

    System.out.println("IN SIM" + localMaybee.screenWidth);
}

public JButton getBtn()
{
    if(btn == null)
    {
        btn = new JButton("ENDE");
        btn.setSize(70, 20);
        btn.setForeground(Color.YELLOW);
        btn.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e) 
            {


            }
        });

    }
    return btn; 
}
}

那么我错过了什么?

非常感谢!

1 个答案:

答案 0 :(得分:3)

直接问题是在JPanel中创建的SimPanel.init()的第二个实例。 SimPanel已经是JPanel,无需维护public JPanel simPanel成员。

同样的问题出现在扩展Maybee的{​​{1}}类中,但维护JFrame成员。

另外,正如上面评论中已经提到的那样(感谢@Frakcool!):

  • 请务必在public JFrame maynFrame之前致电pack();

  • 请勿致电setVisible(),请覆盖setPreferredSize() intead;

  • 无需延长getPreferredSize();

  • 无需致电JFrame上的setVisible;

  • 请勿致电JPanel,这是布局管理员的工作;

  • 不需要btn.setSize()setContentPane()默认情况下JFrame为内容窗格JPanel。在这种情况下,调用BorderLayout就足够了。

以下是原始代码的略微修改版本(为简洁起见而简化):

add()

编辑

该应用程序可能包含许多面板。诸如import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class Maybee2 { static class SimPanel extends JPanel { public SimPanel() { setLayout(new BorderLayout()); JButton btn = new JButton("ENDE"); btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { //TODO } }); add(btn, BorderLayout.CENTER); } @Override public Dimension getPreferredSize() { return new Dimension(300, 200); } } private static void createAndShowGUI() { final JFrame frame = new JFrame("Maybee"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); SimPanel simPanel = new SimPanel(); frame.add(simPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } 之类的高级容器不知道所有底层布局复杂性,并且不能强制执行特定大小。面板本身知道其内部布局及其内容。因此,面板向布局管理器报告其首选大小,布局管理器最终打包内容。有关详细信息,请参阅Laying Out Components Within a Container

JFrame有效,尽管按钮占据setBackground的中心,占据了面板的所有空间。更改面板的布局并查看效果。或者将按钮移动到另一个区域,即 - BorderLayoutA Visual Guide to Layout Managers中阅读更多内容。