1

In the code below, the JFrame contains JLabel only, in the center of BorderLayout.

package test.swing;

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class Try_JLabel_01 {

    public static void main(String[] arg) {

        JFrame frame = new JFrame() {

            JLabel label = new JLabel("label");

            {
                setLayout(new BorderLayout());
                add(label, BorderLayout.CENTER);
            }

        };

        frame.pack();
        //frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);


    }

}

If ran, this program shows window, which fits exactly the control size.

Simultaneously, if I define my custom control, then default window is of zero size:

public class Try_JLabel_02 {

    public static void main(String[] arg) {

        JFrame frame = new JFrame() {

            //JLabel label = new JLabel("label");
            JComponent label = new JComponent() {

                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);

                    g.setColor(Color.RED);
                    g.fillOval(0, 0, 200, 100);
                }
            };


            {
                setLayout(new BorderLayout());
                add(label, BorderLayout.CENTER);
            }

        };

        frame.pack();
        //frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);


    }

}

How to extend JComponent correctly, so that it behaves like JLabel and, for example, has the default size of 200x100?

P.S. I don't want to extend JLabel. I want to learn how JLabel does extending JConmponent instead.

I see source code of JLabel, but I can't understand, how do they control the sizes. Actually I see no any size control code at all there.

UPDATE

I found that can solve the task if I not override, but if I set the sizes:

//JLabel label = new JLabel("label");
        JComponent label = new JComponent() {

            {
                setMinimumSize(new Dimension(200, 100));
                setPreferredSize(new Dimension(200, 100));
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);

                g.setColor(Color.RED);
                g.fillOval(0, 0, 200, 100);
            }
        };

But this works only in case I know sizes myself. In the case of font, I can't know size without having Graphics object first.

So how to determine sizes in case of a font?

Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385

2 Answers2

5

The reason that JLabel (and other components) can generate the results you're seeing is because they provide useful size hints back to parent container, which is used by it's layout manger to make decisions about how best to layout the child components.

All this information is use by pack to determine the best possible size to make the window when you call it.

By default a JComponent's preferred size is 0x0, which isn't very helpful to you. Start by overriding the components getPreferredSize method and return, something like, new Dimension(200, 200);

Now, remember, each layout manager uses different information to make its decision and you may also need to look at getMinimumSize and getMaximumSize as well

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    If you decide to extend `JLabel` and override `getPreferredSize`, beware of this [pitfall](http://stackoverflow.com/a/12532237/230513). – trashgod Oct 07 '13 at 20:28
  • I don't see, that `getPreferredSize()` method is overrided in `JLabel`: http://docs.oracle.com/javase/7/docs/api/javax/swing/JLabel.html – Suzan Cioc Oct 08 '13 at 07:26
  • @SuzanCioc It is likely that the UI delegate is setting the preferred size directly. On your case, you don't have a UI delegate, therefore, you need to supply the result yourself – MadProgrammer Oct 08 '13 at 08:08
  • @MadProgrammer is correct, for [example](http://stackoverflow.com/a/3597688/230513). – trashgod Oct 08 '13 at 12:02
4

I don't want to extend JLabel.

If you don't want to extend JLabel, you can pad the enclosing Container, as shown here using an EmptyBorder.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • @SuzanCioc: No, the label's UI delegate uses the chosen font's geometry, for [example](http://stackoverflow.com/a/3597688/230513). – trashgod Oct 08 '13 at 12:02