有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

swing Java嵌套JPanel未保持指定的大小

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

JPanelwidth 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);                  
    }
}

现在,这个面板应该以50%的宽度嵌套在ControlContainer

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{},这是预期的,但是,当呈现时,它会填充整个ControlContainer

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


共 (1) 个答案

  1. # 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();
            }
    
        }
    
    }