如何正确地从添加到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问题.