如何从添加到JLabel的JComponent返回XxxSize

我怎样才能正确地返回JComponent(s)添加到JLabel中的XxxSize

1。 figure >> lets LayoutManager works like as for JPanel, JLabel returns Size(0, 0)

在这里输入图像描述

第2位。 figure >> added some PreferredSize to the JLabel

在这里输入图像描述

3。 figure >> calculated PreferredSize from JComponent(s) added to the JLabel

在这里输入图像描述

4。 figure >> lets LayoutManager works changed JLabel to JPanel, now LayoutManager correctly calculated Dimension without using any XxxSize

在这里输入图像描述

注意使用Nimbus L&F,所有可用的L&F都有相同的输出

 import java.awt.*; import java.awt.event.*; import java.util.LinkedList; import java.util.Queue; import javax.swing.*; public class NimbusBorderPainterDemo extends JFrame { private static final long serialVersionUID = 1L; private JFrame frame = new JFrame(); private JPanel fatherPanel = new JPanel(), titlePanel = new JPanel(); private JLabel buttonPanel = new JLabel(); //figure ---> 4th. switch JLabel with JPanel //private JPanel buttonPanel = new JPanel(); private Queue<Icon> iconQueue = new LinkedList<Icon>(); public NimbusBorderPainterDemo() { iconQueue.add(UIManager.getIcon("OptionPane.errorIcon")); iconQueue.add(UIManager.getIcon("OptionPane.informationIcon")); iconQueue.add(UIManager.getIcon("OptionPane.warningIcon")); JButton button0 = createButton(); JButton button1 = createButton(); JButton button2 = createButton(); button2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(1); } }); int gap = 5; buttonPanel.setLayout(new GridLayout(0, 3, gap, 0)); buttonPanel.add(button0); buttonPanel.add(button1); buttonPanel.add(button2); // figure 1st. ---> without PreferredSize // figure 2nd. ---> //buttonPanel.setPreferredSize(new Dimension(160, 30)); // figure 3rd. ---> /*Dimension dim = button0.getPreferredSize(); int w = dim.width; int h = dim.height; w = (w + 5) * 3; h += 4; dim = new Dimension(w, h); buttonPanel.setPreferredSize(dim);*/ titlePanel.setLayout(new BorderLayout()); titlePanel.add(new JLabel(nextIcon()), BorderLayout.WEST); titlePanel.add(new JLabel("My Frame"), BorderLayout.CENTER); titlePanel.setBorder(BorderFactory.createLineBorder(Color.GRAY)); titlePanel.add(buttonPanel, BorderLayout.EAST); fatherPanel.setLayout(new BorderLayout()); fatherPanel.add(titlePanel, BorderLayout.CENTER); frame.setUndecorated(true); frame.add(fatherPanel); frame.setLocation(50, 50); frame.pack(); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.setVisible(true); } private JButton createButton() { JButton button = new JButton(); button.setBorderPainted(false); button.setBorder(null); button.setFocusable(false); button.setMargin(new Insets(0, 0, 0, 0)); button.setContentAreaFilled(false); button.setIcon(nextIcon()); //button.setRolloverIcon(nextIcon()); //button.setPressedIcon(nextIcon()); //button.setDisabledIcon(nextIcon()); nextIcon(); return button; } private Icon nextIcon() { Icon icon = iconQueue.peek(); iconQueue.add(iconQueue.remove()); return icon; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (Exception fail) { } UIManager.getLookAndFeelDefaults().put("nimbusFocus", Color.RED); NimbusBorderPainterDemo nimbusBorderPainterDemo = new NimbusBorderPainterDemo(); } }); } } 

默认首选大小计算是使用布局pipe理器来确定组件的首选大小。 这意味着布局pipe理器遍历所有子组件来确定每个子组件的首选大小。 对于用作容器的JPanel,将使用此计算。

但是,对于其他Swing组件,通常会覆盖getPreferredSize()方法以为给定组件提供合理的大小。

在JLabel的情况下,首选的大小计算考虑到文本和使用的图标。 既然你没有提供任何的首选大小是零。 当然,如果使用setPreferredSize()方法手动覆盖此计算,则组件将具有首选大小。

因此,即使Swing允许您将组件添加到任何组件,并使用布局pipe理器来布局子组件,但在首选大小计算中不会使用这些子组件。

这不仅仅是一个灵气问题。