Java嵌套的JPanel不保持指定的大小

时间:2015-02-19 20:16:15

标签: java swing jframe jpanel preferredsize

我有一个JFrame,其中包含2个JPanels,其中一个是JFrame的70%,另一个是剩下的30%。宽度为30%的JPanel内嵌有一个嵌套的JPanel。但是,这个嵌套的JPanel应该是其父JPanel宽度的50%,但是当它显示时,它占用了父JPanel的全宽。

JPanel属于width 358height 772,嵌套JPanel具有以下值:width 179height 772

我已将这些组件的颜色设置为绿色和灰色,因此我可以很容易地看到它们是否正确渲染。当我运行我的应用程序时,嵌套的JPanel实际上被渲染,好像它是parent的整个宽度(整个区域呈现为绿色)。

这是当前的代码。

public class DisplayFrame extends JFrame{

    private final static int WIDTH = 1200;
    private final static int HEIGHT = 800;      
    private DisplayCanvas canvas;   
    private ControlContainer controlContainer;

    public DisplayFrame() {    
        //simple inheritance. 
        super(title);
        setSize(new Dimension(WIDTH, HEIGHT));
        setResizable(false);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);    
        addComponents(this.getContentPane());    
    } 

    public void addComponents(Container container){
        canvas = DisplayCanvas.getInstance(container);    
        canvas.setAlignmentX(Component.LEFT_ALIGNMENT);
        container.add(canvas);          
        controlContainer = ControlContainer.getInstance(container);    
        controlContainer.setAlignmentX(Component.RIGHT_ALIGNMENT);
        container.add(controlContainer);
    }    
}

宽度为70%的面板

public class DisplayCanvas extends JPanel{

    private final double WIDTH_PERCENT = 70;    
    private static DisplayCanvas instance;

    private DisplayCanvas(Container parent) {    
        this.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT, 
            parent.getWidth()), parent.getHeight()));
        this.setBackground(Color.WHITE);
        this.setVisible(true);    
    }
    //implement the singleton 
    public static DisplayCanvas getInstance(Container parent) {    
        if(instance != null){
            return instance;
        }    
        instance = new DisplayCanvas(parent);    
        return instance;
    }
}

宽度为30%的面板:

public class ControlContainer extends JPanel{

    private final double WIDTH_PERCENT = 30;
    private static ControlContainer instance;
    private ControlPanel controlPanel;

    private ControlContainer(Container parent) {
        this.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT, 
             parent.getWidth()), parent.getHeight()));
        this.setBackground(Color.GRAY);
        this.setLayout(new BorderLayout(0,0));
        this.setVisible(true);
        addControlElements(this);           
    }

    //implement Singelton
    public static ControlContainer getInstance(Container parent){    
        if(instance != null){
            return instance;
        }    
        instance = new ControlContainer(parent);        
        return instance;    
    }

    public void addControlElements(Container parent){           
        controlPanel = ControlPanel.getInstance(parent);
        controlPanel.setAlignmentX(LEFT_ALIGNMENT);         
        System.out.println("ControlContainer: " + parent.getWidth() 
             + "       " + parent.getHeight()+ " vis: " + parent.isVisible());
        System.out.println("ControlPanel: " + controlPanel.getWidth() 
             + "       " + controlPanel.getHeight() + " vis: " + controlPanel.isVisible());
        parent.add(controlPanel, BorderLayout.CENTER);                  
    }
}

现在,此面板应嵌套在ControlContainer内,宽度的50%。

public class ControlPanel extends JPanel{       

        private final double WIDTH_PERCENT = 50;        
        private static ControlPanel instance;

        private ControlPanel(Container parent) {
            super.setSize(new Dimension(MathHelper.calculateXPercentOfY(WIDTH_PERCENT, 
                  parent.getWidth()), parent.getHeight()));
            super.setBackground(Color.GREEN);
            super.setVisible(true);        
        }

        //implement singelton measures
        public static ControlPanel getInstance(Container parent){        
            if(instance != null){
                return instance;
            }        
            instance = new ControlPanel(parent);        
            return instance;        
        }
    }

这是addControlElements方法的输出:

ControlContainer: 358       772 vis: true
ControlPanel: 179       772 vis: true

这仅用于测试值是否按预期设置,因为您可以看到ControlPanel width is 179这是预期的,但是在渲染时它会填充整个{{1} }。

希望你理解我的意思,这不是最容易解释的。

1 个答案:

答案 0 :(得分:1)

首先看看Laying Out Components Within a Container,了解如何在Swing中使用组件。看看How to Use GridBagLayout,了解如何实现您正在寻找的结果

Test

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new BasePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class BasePane extends JPanel {

        public BasePane() {
            TestPane top = new TestPane();
            TestPane bottom = new TestPane();

//          top.setBorder(new LineBorder(Color.RED));
//          bottom.setBorder(new LineBorder(Color.BLUE));

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 1;
            gbc.weighty = 0.3;

            add(top, gbc);

            gbc.gridy++;
            gbc.weighty = 0.7;

            add(bottom, gbc);
        }

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


    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            Dimension mySize = getSize();
            Dimension parentSize = getParent().getSize();

            String widthPer = NumberFormat.getPercentInstance().format((float) mySize.width / (float) parentSize.width);
            String heightPer = NumberFormat.getPercentInstance().format((float) mySize.height / (float) parentSize.height);

            String[] text = new String[]{
                "Me = " + mySize.width + "x" + mySize.height,
                "Parent = " + parentSize.height + "x" + parentSize.height,
                "Perctange = " + widthPer + "x" + heightPer
            };

            FontMetrics fm = g2d.getFontMetrics();
            int y = (getHeight() - (fm.getHeight() * text.length)) / 2;
            for (String value : text) {
                int x = (getWidth() - fm.stringWidth(value)) / 2;
                g2d.drawString(value, x, y + fm.getAscent());
                y += fm.getHeight();
            }

            g2d.dispose();
        }

    }

}