When does a JTabbedPane component get its size?

2019-07-16 03:48发布

问题:

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?

回答1:

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]


回答2:

when does the Component get its size?

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

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



回答3:

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