Get size of JPanel before realizing - java

I've created JPanel and have already added components into it and I'm going to pass that JPanel to PopUpFactory... So can I get size of JPanel before passing it?
I put Jlabel into it and text after that and I don't know the size of that text...

You can set the preferred size using setPreferredSize(Dimension); e.g.
JPanel pnl = new JPanel(new BorderLayout());
pnl.setPreferredSize(new Dimension(640, 480));
This value will subsequently be obtainable by calling getPreferredSize() and will be used when laying out the component, although note that it is not guaranteed that it will actually be rendered at this size.
Why do you actually require the size prior to rendering it? Typically with Swing programming you don't need to deal with explicit dimensions / sizes as the chosen layout will take care of these specifics for you.
EDIT
To address the OP's query regarding JTextField, one option here it to call the int based constructor that accepts the anticipate number of columns. This causes the text field to be rendered wide enough to support that number of characters.
My second point addresses the comment that the setXXXSize methods should never be called directly and that the developer should rely solely on the LayoutManager. This is not always appropriate - Typically it is necessary to set the preferred size of your main application frame. For example, suppose I were writing a a simple browser application in Swing. The majority of the main frame is a JEditorPane for rendering HTML. If I do not set a preferred size for this component (or the containing frame) and I call pack() the frame is likely to be rendered as small as possible, rather than with sensible dimensions.

JComponents doesn't returns getSize, getLocation, getBounds or getXxxSize if a JComponents hasn't been previously visible on the screen or after call pack()
but why care about that, because usage of (proper and correct) LayoutManager can do that automatically, that reason why LayoutManager exist there, really why care about that

Just call getPreferredSize method for JLabel.No matter if container of it is not realized, preferred size changes if you are setting text of jlabel even before you set it visible.

Related

JButton size larger than specified

I created a jframe, added a jbutton to it, and set the size of the jframe as 500,500 and size of the jbutton as 40,60. However, when I executed my program, my jbutton was covering the whole of my jframe. I
tried many things and looked into many sources, but I could not find a solution.
Please help me solve this.
You're not using a LayoutManager of any kind. The JButton will try to inherit the size of the parent container, as the default for a JFrame is BorderLayout (specifically, BorderLayout.CENTER). You could try using
button.setPreferredSize(x, y);
However I don't think this would be enough by itself. Call getContentPane on the Jframe, and set a layout on that contentPane container (I use FlowLayout a lot, as it respects setPreferredSize). Put your JButton inside that.
This is always a good starting point:
https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
As the methods that you can call on a UI element vary depending on what LayoutManager you're assigning them to (be the child of). Sometimes it's setMinimumSize, sometimes it's setPreferredSize, and sometimes it's a combination.

Setting size on JLabel displaces other components in java

I am setting a JLabel for the error messages in my program, so initially the label is empty label.setText(""), but when there is an error it should change to something like label.setText("Error, you have entered invalid data...").
If I use setSize(x,y) on the label, it forces other components to displace when error message takes place. But using setPreferredSize(Dimension(x,y))doesn't impact them.
Q1. Why is that?
Q2. What is the difference between setSize(x,y) and setPreferredSize(Dimension(x,y))
Q3. Does it have to do anything with layout?
Thank you in advance for explanation!
P.S. I am using GridBagLayout for positioning my components on the JPanel.
Don’t use the setSize method.
setSize is called by LayoutManagers, like GridBagLayout, to lay out child components. When you call setSize explicitly, you are fighting with the GridBagLayout. Eventually, GridBagLayout will undo your setSize call, when it calls setSize for its own purposes.
In other words, any call to setSize eventually will be wiped out by the parent layout.
setPreferredSize will not be wiped out. Most LayoutManagers, including GridBagLayout, do their best to respect a component’s preferred size.
However, you should not be calling setPreferredSize. Components already have a preferred size by default, and it is almost certainly better than any numbers you can come up with. For instance, a JLabel’s default preferred size is the size which is just large enough to accommodate its text, icon, and borders.
Computing a preferred size is harder than you might think. How many pixels does text use? How many pixels high is a 12 point font? 12 points is not 12 pixels. 12 points is 12⁄72 inch. How many pixels is that? It depends on the user’s monitor and graphics resolution. All of this is known to the Swing rendering system, and JLabel uses all of that information to determine its default preferred size. You should not try to reinvent all of that work, and you should not try to replace that work with something simpler, as it will be inadequate.
If you just let the JLabel keep its preferred size, GridBagLayout will do its best to accommodate that. If the window itself does not have room to display the JLabel’s new text, you probably should call the window’s pack() method after changing the text.
Update: This appears to be an XY problem—you really want a message that you can show and hide.
You want your layout to be big enough to accommodate your message text as soon as you create it. This is typically done with a CardLayout, which lets you place several components on top of each other, with only one of them visible at any given moment. Since you want to show no text at all, initially, you would add an empty JLabel as the first component in the CardLayout, so it is shown by default:
JLabel label = new JLabel("Error, you have entered invalid data...");
CardLayout messageLayout = new CardLayout();
JPanel messagePane = new JPanel(messageLayout);
messagePane.add(new JLabel(), "blank");
messagePane.add(label, "message");
// Do not add label directly to your user interface.
// Add messagePane instead.
mainWindow.add(messagePane);
// ...
// Show message
messageLayout.show(messagePane, "message");
// ...
// Hide message
messageLayout.show(messagePane, "blank");
"message" and "blank" are never seen by the user. They are just unique identifiers for each component (“card”) in the CardLayout. You can make them anything you want.
The setSize() function sets the size not based on any LayoutManager. Thats why you should always use setPrefferedSize() when working with a LayoutManager. setPrefferedSize() firstly tries to be conform with the LayoutManagers dimensions if then possible Java tries to set the size of the Label according to your setPrefferedSize() input.
So yes, it does have anything to do with layout. If possible, you should only use setPrefferedSize() as you are working with layout managers.

Difference end result between setFont and setPreferredSize

In a Layout Manager when I use setPreferedSize it increased the size of JLabel but show only one word like (JLabel = Name) after using setPreferedSize JLabel becomes like N.... But setFont works correctly..
Can anyone tell the exact difference between the behavior of setFont and setPreferredSize?
But setFont works correctly..
Exactly, and that is the only method you should use. When you use the setFont() method, the component is responsible for determining the preferred size. The component will take into account information like the font, text, border to determine it's preferred size.
When you invoke setPreferredSize(), you are telling the component that you know better, which you don't because you are just making a guess. If your guess is too small you see the "..." because there is not enough space to paint the entire text.
Don't use setPreferredSize()!

add()ing to a JPanel breaks its size

I have a JPanel identified by myPanel. I create a series of JButtons, and add() them to myPanel. At the end of my generating-and-adding loop, I call myPanel.validate(). The buttons show up.
The problem is the size of the panel is affected. No matter what Layout Manager I choose, the buttons are always added on the same line (even though there is more space beneath them).
I have tried setting myPanel's maximum size and setting its size after every add(). No matter what I do, after that validate(), the panel is blown up and my application's GUI is screwed.
Any ideas?
I create a series of JButtons, and add() them to myPanel... the buttons are always added on the same line (even though there is more space beneath them).
None of the default layout managers provide automatic wrapping. You need to specify how you want wrapping to occur. A GridLayout or a GridBagLayout can be used in these cases.
Or you can try the Wrap Layout which was written for this purpose.
i would firstly set a preferred size on the jpanel:
myPanel.setPreferredSize(new Dimension(X, Y));
this will tell your layout manager how to try to fit the contents within this dimension.
without seeing your source code, i can't add much more than that.

How to find out the preferred size of a JPanel which is not displayed, according to its content?

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)?
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.
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();

Categories