I am using a JTable in a program. The problem is that when I set the size of the whole JTable, I am using this method:
setPreferredScrollableViewportSize(Dimension size)
The question I have is that when using this method, you enter in the width and length in pixels. Will there be issues (formatting-wise) when the program is run on different computers/machines?
Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? - Short answer is yes (you should avoid it)
When setting the preferredSize of the table, you are not actually taking into account the number of rows or columns which the table might have, depending on the layout manager, it may NEVER be larger than the dimensions you provide, regardless of the amount of data
The question I have is that when using this method, you enter in the width and length in pixels. Will there be issues (formatting-wise) when the program is run on different computers/machines?
Generally, yes.
JTable was designed to be shown within a JScrollPane, which allows you some leeway with this, as the JTable can grow and shrink, within the JScrollPane, but the JScrollPane can remain the same.
Having said that, you should NOT be using setPreferredSize and especially not messing with JTables, JTable calculates it's own preferred size based on the needs of the data...and it does a reasonably good job.
If you want to change the size the JScrollPane, then you will need to change the result of getPreferredScrollableViewportSize which lets the JScrollPane know how big a component would like the basic viewable area to be, under optimal conditions
See How to Use Tables and How to Use Scroll Panes
Related
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.
I am trying to create a GUI for a program with an undefined number of rows but stay with two columns. Currently the only way I can get it to look how I want is using FlowLayout but the window of course needs to be smaller than desired. It needs to happen within one panel as well because it is being added to a tabbed pane.
What would be the best layout manager to solve the problem that is in the JDK? Or would just kind of brute forcing it with AbsoluteLayout be the best approach (as the user shouldn't really be resizing the window)?
I have attached the desired appearance.
Thanks for any help in advance.
Several layouts can do what you want. I'd suggest GridLayout (easy to use, but columns will be equal width) or GridBagLayout (harder to use, but you have lots of control). You could also use a BorderLayout and put all the fields in a sub-panel on the WEST and all the drop-downs in a sub-panel on the EAST. The difficulty with that is ensuring that the rows have the same height, since they won't be constrained by the layout itself.
The best thing to do would be to go through the Java tutorial on layouts and get up to speed on what the various layout managers can do.
Also, since you're using Swing, you could just use a JTable (as Gilbert Le Blanc suggests in his comment).
I have a JCombobox and I'm adding some items at runtime. Some of them are very long and my Jcombobox is growing very long too. It's in a JPanel container with BoxLayout (PAGE_AXIS). I have no idea how to prevent growing...
I wonder there should be a property like overflow and in combobox item will be shown like "123..." if it's "123456789".
EDIT:
I read your answers, thank you very much. But the problem is that my JPanel can resize and I need to make it's children always fill parent. So I cant set preferred size because my JPanel's size can change at runtime.
And I also can't set maximum size or use setPrototypeDisplayValue() because of the same reason.
I tried to use other layouts (GroupLayout, BorderLayout) but the result is the same.
I can post code if you want but I think it's not necessary. Let me know if you need it anyway.
Just tried with JTextArea with single row instead of JCombobox. Result is the same. It's growing when I type.
I solved similair issue by overrode JComboBox.setPrototypeDisplayValue()
and there are two ways (as mentioned #Stas) resize JComboBox or its derived Popup or both together
You can try this :
myCombo.setPreferredSize(new Dimension(myCombo.getHeight(), myCombo.getWidth()))
There are multiple solutions for the problem. You can change layout to limit growing.
Or fix somehow max size of the combobox
Or add a custom renderer (extending default renderer) and set preferred size there.
My friend is facing an issue where in he has a Swing Dialog and it has several text fields, combo boxes and radio buttons. Also it has a JPanel which holds the search results if at all the user wants to perform any search.
It looks fine with normal font size. But once the font size is increased to say 150% or even 200%, then the text boxes are not growing and the text in them is growing. So, they are not fitting in and are getting clip-ed.
He managed to overcome this limitation by using the setPreferredSize method on the UI components. Now it seems that he is able to control the behaviour in case of text boxes, combo boxes etc. But the search panel is still an issue.
Could some one please point out what the issue could be?
UPDATE:
They also have a JTable where the search results are displayed. Now, the thing is, they are hardcoding the height of each row in that JTable using the call setRowHeight. And due to this, if the font size is increased, the row height still remains the same. Is there any method call that resolves this.
We honestly think that they should not have done that hardcoding. Is there any solution for this? Please share.
Thanks,
Pavan.
Which layout is your friend using? Choosing a suitable layout may help.
Try pack() it will automatically adjust the Window to fit the preferred size of the components.
I'm writing a custom file selection component. In my UI, first the user clicks a button, which pops a JFileChooser; when it is closed, the absolute path of the selected file is written to a JTextField.
The problem is, absolute paths are usually long, which causes the text field to enlarge, making its container too wide.
I've tried this, but it didn't do anything, the text field is still too wide:
fileNameTextField.setMaximumSize(new java.awt.Dimension(450, 2147483647));
Currently, when it is empty, it is already 400px long, because of GridBagConstraints attached to it.
I'd like it to be like text fields in HTML pages, which have a fixed size and do not enlarge when the input is too long.
So, how do I set the max size for a JTextField ?
It may depend on the layout manager your text field is in. Some layout managers expand and some do not. Some expand only in some cases, others always.
I'm assuming you're doing
filedNameTextField = new JTextField(80); // 80 == columns
If so, for most reasonable layouts, the field should not change size (at least, it shouldn't grow). Often layout managers behave badly when put into JScrollPanes.
In my experience, trying to control the sizes via setMaximumSize and setPreferredWidth and so on are precarious at best. Swing decided on its own with the layout manager and there's little you can do about it.
All that being said, I have no had the problem you are experiencing, which leads me to believe that some judicious use of a layout manager will solve the problem.
I solved this by setting the maximum width on the container of the text field, using setMaximumSize.
According to davetron's answer, this is a fragile solution, because the layout manager might disregard that property. In my case, the container is the top-most, and in a first test it worked.
Don't set any of the sizes on the text field. Instead set the column size to a non-zero value via setColumns or using the constructor with the column argument.
What is happening is that the preferred size reported by the JTextComponent when columns is zero is the entire amount of space needed to render the text. When columns is set to a non-zero value the preferred size is the needed size to show that many standard column widths. (for a variable pitch font it is usually close to the size of the lower case 'm'). With columns set to zero the text field is requesting as much space as it can get and stretching out the whole container.
Since you already have it in a GridBagLayout with a fill, you could probably just set the columns to 1 and let the fill stretch it out based on the other components, or some other suitably low number.