如何正确地从添加到JLabel的JComponent返回XxxSize
1.图>>让LayoutManager像JPanel一样工作,JLabel返回Size(0,0)
第2位.图>>将一些PreferredSize添加到JLabel
3.图>>从添加到JLabel的JComponent计算的PreferredSize
4.图>>让LayoutManager将JLabel改为JPanel,现在LayoutManager正确计算了Dimension而不使用任何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)); 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(); } }); } }
解决方法
默认的首选大小计算是使用布局管理器来确定组件的首选大小.这意味着布局管理器遍历所有子组件以确定每个子组件的首选大小.对于要用作Container的JPanel,使用此计算.
但是,对于其他Swing组件,始终会覆盖getPreferredSize()方法,以便为给定组件提供合理的大小.
对于JLabel,首选大小计算会考虑使用的文本和图标.由于您没有提供任何首选大小为零.当然,如果您使用setPreferredSize()方法手动覆盖此计算,则组件将具有首选大小.
因此,即使Swing允许您向任何组件添加组件并使用布局管理器来布局子组件,这些子组件也不会在首选大小计算中使用.
这不仅仅是一个Nimbus问题.