tags:

views:

216

answers:

2

I am using a JPanel (with several labels inside) to add a dynamic information on a graph. This panel is dynamically created, it is not visible before I use it to draw.

For this, I am using a BufferedImage, and I follow approximately the same steps as described on this other question. It works good, as long as I specify all sizes (the panel, and its components).

Like asked as well in comments of the referred question, how can I determine the optimal size of this panel? The same operation would be done if this panel was displayed in a regular frame/layout setting.

In my case, how can I "pack", in a way, this panel, so that its size, and size of its content are set to the optimal (determined by the size of labels, then)?

+1  A: 

The direct answer is to call Window#pack(). This method will automatically set the size of all underlying children to thier preferred sizes(ofcourse this depends on layouts of child containers, for e.g. BorderLayout doesent give a damn about preffered sizes).

So as long as you have set preferred sizes(or min/max sizes in case layouts are like BorderLayout) of your child components, pack() method will be all you need.

[UPDATE]
One way is to do is add a HierarchyListener to your jpanel and check for HierarchyEvent#DISPLAYABILITY_CHANGED events. This event is called when your panel is realized that is ready to be shown(and a parent is available), at this moment you can do:

SwingUtilities#getWindowAncestor(myPanel).pack();

Suraj Chandran
This method would work if my panel was in a window, but it is not. I'm dynamically creating this panel, to draw directly with it. It is not visible in any window before I use it myself. The question is more "how to have the same effect as a *pack()*, without a Window".
Gnoupi
Would putting it in a JFrame and calling pack and then removing the panel work? :)
willcodejavaforfood
@willcodejavaforfood - I've just tried, it does work, but that seems a bit overkill to add a JFrame to the process ;)
Gnoupi
@Gnoupi...even if its in a panel, finally you need to add the panel in a window for the user to see it rt? Then you can call the parentWindow.pack().
Suraj Chandran
@Suraj - I don't, I use this panel to draw an image, and this image is passed to the graph object. I could eventually use the panel to paint directly over the graph myself, the issue would be the same: this panel won't be added to any container.
Gnoupi
@Gnoupi...i have update my answer...maybe the update is what you need.
Suraj Chandran
@Gnoupi - Well if it works... :)
willcodejavaforfood
@Suraj - He was talking about his own short solution, to embed it in a temporary JFrame.
Gnoupi
@Gnoupi...did u try the update in my answer!! does it help?
Suraj Chandran
@suraj, like I said, this panel doesn't even have a window ancestor, since it is not added to any window. So it doesn't work, sorry. Thanks for your answer anyway, it put me on the right track ;)
Gnoupi
+1  A: 

Suraj and willcodejavaforfood put me on the good track.

Checking what is actually done in a pack() method, I see that this is mostly setting the current size to the one returned by getPreferredSize().

From this, I managed to make such solution:

// Creating the panel
JPanel lPanel = new JPanel();
//lPanel.setSize(1000, 1000); //default size, not needed anymore
lPanel.setLayout(new BoxLayout(lPanel, BoxLayout.PAGE_AXIS));

//Adding the content
lPanel.add(new JLabel("Blah"));
// etc...

//Adjust the panel to its preferred size
lPanel.setSize(lPanel.getPreferredSize());

//Call the layout method 
//(this will adjust the content components to their correct size and position)
lPanel.doLayout();

This method works correctly, and adjusts the panel and its content to the correct size (and answers my question in a simplistic way: "how to find the preferred size? getPreferredSize()").

However, it requires to set the initial size to a large enough size, so that the content fits in, or they won't be put on the layout. This is a bit pity, and not really "clean", but I can't find a way to avoid that, for now.

Edit: Actually, the default size was not necessary, because getPreferredSize() returns the correct value, even before calling doLayout(). As such, the panel can be set to its proper size before calling the layout method.

Gnoupi