0

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.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
sumu00
  • 49
  • 7
  • Have you considered using a non-editable `JTextField` (removing the borders), it will allow the text to overflow without resizing the field. Not my most recommend solution. I'd also discourage the use of `minimumSize` unless you're prepared to override the method and make use of appropriate functionality to calculate the size (taking into account font metrics and other graphics information), but again, that "might" be a way to go. You'd then need to provide a means that could truncate the text ("This is long ...") which would probably need to override `getText` – MadProgrammer Feb 28 '18 at 22:36
  • `so resizing label by adding text is just messing other components.` - why? Generally an error label would be on its own line so it won't affect other components. What do you expect to happen? You have a problem with your layout. We have no idea what you layout is so how do you expect us to make suggestions??? Post a proper [mcve] EVERY time you ask a question so we know exactly what you are talking about.. – camickr Mar 01 '18 at 02:58

2 Answers2

5

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 1272 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.

VGR
  • 40,506
  • 4
  • 48
  • 63
  • thanks. But I tried not to set any size, the program still moves other components when there is a longer text. It seems to me that when creating an empty label and running the program, it gives as much space as it was initialised (meaning empty), so resizing label by adding text is just messing other components. I know preferredSize is very tricky, but in my case, I can't use setSize() or just leave it to layout to manage. Any ideas? Thanks. – sumu00 Feb 28 '18 at 22:12
  • @sumu00 Updated answer. You probably want a CardLayout. – VGR Mar 01 '18 at 03:07
2

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.

DarkCruncher
  • 41
  • 1
  • 8
  • *"you should only use setPrefferedSize()"* See [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?](http://stackoverflow.com/q/7229226/418556) (Yes.) – Andrew Thompson Mar 01 '18 at 02:15