2

I need to know the size of a JPanel when I add it to a JTabbedPane to compute other values. If I call the add(Component) method, when does the Component get its size?

For example,

JTabbedPane tabbedPane = new JTabbedPane();
JPanel panel = new JPanel();
panel.setBackGround(Color.RED); // pretty colors!
tabbedPane.add(panel);

int newTabIndex = tabbedPane.indexOfComponent(panel);
tabbedPane.setSelectedIndex(newTabIndex);

Thank you in advance!

Edit @mKorbel suggested setting the visibility of the JPanel to true:

JTabbedPane tabbedPane = new JTabbedPane();
JPanel panel = new JPanel();
panel.setBackGround(Color.RED);
tabbedPane.add(panel);
panel.setVisible(true); // NEW LINE


int newTabIndex = tabbedPane.indexOfComponent(panel);
tabbedPane.setSelectedIndex(newTabIndex);

Unfortunately, when I applied this change to my own program, the JPanel still had a width and height of 0 and 0, respectively. What else can I try?

joshreesjones
  • 1,934
  • 5
  • 24
  • 42
  • Sounds like your using a null layout. Components will only be sized, automtiacally, if the container they are attached to is using a layout manager. Equally, if the parent component is not valid (not attached to a component that has a native peer, they will not be sized either – MadProgrammer May 17 '13 at 20:31
  • How can I set the layout of a tab? When I think about a tab, I conceptually think of it as something that displays another component, such as a JPanel, and not as something that has a layout. – joshreesjones May 17 '13 at 23:46
  • There are 3 elements at play here. There JTabbedPane, which is managing the tabs and there associated components. The tabs & the component that is associated with the tab. You can control the tab (component) and the view. As shown, if you want to change the tabs layout, you need to supply your own component. You control the layout of view as you would any component – MadProgrammer May 17 '13 at 23:51
  • If I set the tab component to a JPanel (we will call it panel1), set the layout of panel1, set the layout of panel1, and add another JPanel (panel2) to panel1, will panel2 have a defined width and height when I add panel2 to panel1? – joshreesjones May 18 '13 at 00:07
  • Maybe I should ask that as a separate question... – joshreesjones May 18 '13 at 00:07
  • You've to remember also, that unless the tabbed pane is added to a container that us valid, nothing will be laid out – MadProgrammer May 18 '13 at 00:23

3 Answers3

3

JTabbedPane won't be sized until it is attached to a container that is capable of laying it out.

Window#packs job is to determine the preferred size of the child components and size them based on the requirements of the layout manager.

Only at this time would a component (and your JTabbedPane) be sized.

Components may be resized in response to changes in the container hierarchy as well, but the basic process is the same. The JTabbedPanes parent container will decide when it needs to update it's contents and perform a new layout operation, resizing the components based on it's needs

None of your examples show the tabbed pane been added to a parent container...

Updated with simple test...

The following example basically demonstrates when a component would be resized.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestTabSize {

    public static void main(String[] args) {
        new TestTabSize();
    }

    public TestTabSize() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JPanel panel = new JPanel() {
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(200, 200);
                    }
                };

                panel.addComponentListener(new ComponentAdapter() {
                    @Override
                    public void componentResized(ComponentEvent e) {
                        System.out.println("Resized to " + e.getComponent().getSize());
                    }

                    @Override
                    public void componentMoved(ComponentEvent e) {
                        System.out.println("Moved to " + e.getComponent().getLocation());
                    }
                });

                System.out.println("Before been added = " + panel.getSize());

                JTabbedPane tabbedPane = new JTabbedPane();
                tabbedPane.addTab("test", panel);

                System.out.println("Before been added to tab = " + panel.getSize());

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                System.out.println("Before been added to frame = " + panel.getSize());
                frame.add(tabbedPane);
                System.out.println("After been added to frame = " + panel.getSize());
                frame.pack();
                System.out.println("After been packed = " + panel.getSize());
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                System.out.println("After been visible = " + panel.getSize());
            }
        });
    }

}

Output...

As you can see from the output, until the frame is packed, nothing is sized

Before been added = java.awt.Dimension[width=0,height=0]
Before been added to tab = java.awt.Dimension[width=0,height=0]
Before been added to frame = java.awt.Dimension[width=0,height=0]
After been added to frame = java.awt.Dimension[width=0,height=0]
After been packed = java.awt.Dimension[width=200,height=200]
After been visible = java.awt.Dimension[width=200,height=200]
Resized to java.awt.Dimension[width=200,height=200]
Moved to java.awt.Point[x=11,y=33]
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

when does the Component get its size?

  1. after JFrame.pack() (not your issue)

  2. isVisible() is already true (your issue) in the GUI

rob
  • 6,147
  • 2
  • 37
  • 56
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • visible is true by default ;-) – kleopatra Aug 08 '13 at 08:16
  • please question was ---> when does the Component get its size? == JComponent can returns Dimension <> [0, 0] in the cases 1. already visible on the screen, or 2. after pack(), and :-) 3. AbsoluteLayout by using Insets – mKorbel Aug 08 '13 at 10:28
  • repeating: isVisible() returns true _by default_ - independent of whether or not the component is actually _showing_ ... – kleopatra Aug 08 '13 at 10:53
  • crazy summer, aaach now can I seee, you are right `isVisible` != `is already visible`, – mKorbel Aug 08 '13 at 11:46
0

JTabbedPane's size is determined by the size of the largest component that's added into it. In your case, the size of the JPanel must be set using JPanel.setPreferredSize() method. This will ensure that JPanel gets rendered properly

  • This is not entirly true. Yes the `JTabbedPane`'s preferred size will be the largest preferred size of all the components added to it, but it is up to the parent container's layout manager to determine the actual size given to the tabbed pane, which may be smaller then the preferred size... – MadProgrammer May 18 '13 at 01:36