I'm having problems with my GridLayout whereby a JTextField widens to fit an entry longer than the initial size. Another poster with this problem was told SpringLayout was the easiest solution, so that's what I'm trying. However I'm having problems getting this panel to even display.
I've top, bottom, left, and right panels each with different layouts that are set in a top-level panel (the only one in this frame). This SpringLayout I'm trying is to be in the right panel (added to the top panel as topPanel.add(springPanel, BorderLayout.EAST - this was how I did it when this panel was a GridLayout). The code below is modeled after the SpringLayout Oracle tutorial. Sorry I'm new to this layout and am only using it to use fixed widths for JTextFields.
JPanel testPanel = new JPanel();
SpringLayout layout = new SpringLayout();
testPanel.setLayout(layout);
JLabel label = new JLabel("First field: ");
JTextField field = new JTextField("enter text");
testPanel.add(label);
testPanel.add(field);
layout.putConstraint(SpringLayout.WEST, label, 5, SpringLayout.WEST, testPanel);
layout.putConstraint(SpringLayout.NORTH, label, 5, SpringLayout.NORTH, testPanel);
layout.putConstraint(SpringLayout.WEST, field, 5, SpringLayout.EAST, label);
layout.putConstraint(SpringLayout.NORTH, field, 5, SpringLayout.NORTH, testPanel);
...
topPanel.add(testPanel, BorderLayout.EAST);
Any guidance would be appreciated. Thanks.
EDIT: Adding the cols argument doesn't seem to work, but I'll keep trying. The same problem exists with GridBagLayout. Tabbing to the next field doesn't re-size the previous field, but clicking outside those fields elsewhere in the frame causes it to expand the length of its containing text which is what I need to avoid. And I don't have enough rep pts to post images of what I'm doing
EDIT2: Adding cols works - I tried that at some point. Not entirely sure how it's working, but any value (1, 10, 15 tested) seems to fix the length so leaving that panel's focus no longer causes a size change. Thanks!
#Andrew Thompson's answer worked - use col arg to specify # of columns (any number seems to work). Thank you!
Related
I'm developing a game called GalaxyWar, and I am trying to make a map selection menu. I found a problem that when I am using a BoxLayout with BoxLayout.Y_AXIS on a JPanel with setAlignmentX(CENTER_ALIGNMENT), the subcomponents (JPanel's) with assigned size, take up the entire height of the panel (all together), instead of the assigned height!
Here is my code:
scrollPane = new JScrollPane();
scrollPane.setBounds(160, 11, 452, 307);
add(scrollPane);
mapContainer = new JPanel();
mapContainer.setAlignmentX(CENTER_ALIGNMENT);
mapContainer.setAlignmentY(JPanel.TOP_ALIGNMENT);
mapContainer.setLayout(new BoxLayout(mapContainer, BoxLayout.Y_AXIS));
scrollPane.setViewportView(mapContainer);
JPanel demoPanel = new JPanel();
demoPanel.setLayout(null);
demoPanel.setBackground(Color.YELLOW);
demoPanel.setSize(50, 100);
mapContainer.add(demoPanel);
I've researched on this for long, but couldn't find any solutions so far.
try to check out
setPreferredSize()
setMaximumSize()
setMinimumSize()
set all 3 to the same value.
If it still doesn't work, you can try to put the panel, of which you are trying to set the size to fixed, inside another panel.
I got an issue with my JScrollpane. I am adding Labels to it, out from a list. The adding is working and I see the labels. The amount of Labels added is unknown to me, so it can appear that the border of the scrollpane wont be enough. Thats the advantage of using a Scrollpane, so that I can actually scroll down if needed. But the scrollbar doesnt appear. I know there are many questions like that asked, but I tried almost every proposed suggestion. I tried setPreferredSize(), setLayout(), scrollPaneApps.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS), but nothing of it worked.
public DisplayProperties() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setLayout(null);
contentPane.setPreferredSize(new Dimension(450,300));
JScrollPane scrollPane1 = new JScrollPane();
scrollPane1.setBounds(15, 54, 195, 202);
scrollPane1.setViewportBorder(new LineBorder(new Color(0, 0, 0)));
scrollPane1.setPreferredSize(new Dimension(185,195));
scrollPane1.setLayout(null);
scrollPane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
contentPane.add(scrollPane1);
int b = 0;
for(String s : XMLParser.ApplicationsListGUI)
{
b = b + 20;
JLabel lbl = new JLabel("lbl"+s);
lbl.setText(s);
lbl.setBounds(10,b,100,15);
scrollPane1.add(lbl);
scrollPane1.revalidate();
lbl.setVisible(true);
}
}
So why doesnt this Scrollbar dont appear?
You appear to have two JScrollPanes involved, scrollPaneApps, which you set a vertical scrollbar policy, which you try to add a component to, but which you never add to the GUI, and scrollPane1, which you don't set a policy, never add components to, but do add to the GUI. Sorry, but this is totally crazy. You need to fix this so that your code makes sense:
Add the actual JScrollPane that has its vertical scrollbar policy set to the GUI. If it's not added to the GUI, it makes sense that it will never be seen.
Don't add components directly to the JScrollPane but rather to its JViewport via the setViewportView(...) method. Or you can add a component to the JScrollPane constructor which is little more than syntactic sugar for adding it to the viewport.
Avoid null layouts and absolute positioning (avoid setBounds(...)). Using these will make your GUI's rigid, ugly, and almost impossible to improve upon later. Never set a JScrollPane's layout as null, for if you do, it will stop working. Completely.
It doesn't show since you have no layout for the scrollPaneApps panel. So remove this line and it should show.
scrollPane1.setLayout(null);
Hope it helps.
Right now I have the following code which adds the JLabel to the top center of the Panel, which I assume is the default
imageLabel = new JLabel();
ImageIcon customer1 = new ImageIcon("src/view/images/crab.png");
imageLabel.setIcon(customer1);
storePanel.add(imageLabel);
imageLabel.setBounds(20, 20, 50, 50);
setBounds obviously isn't putting it at 20,20....so how do you position something to a point within a Panel?
Use the appropriate LayoutManager to place components in the panel.
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
In your case you should be able to use a FlowLayout and set the horizontal and vertical gaps when you create it.
http://docs.oracle.com/javase/7/docs/api/java/awt/FlowLayout.html#FlowLayout(int,%20int,%20int)
Seems your storePanel is JPanel and has default FlowLayout manager, because of your setBounds(20, 20, 50, 50); doesn't work. It will be work with null layout (storePanel.setLayout(null);).
But I recommend you to use LayoutManager.
If you don't mind a bit of manual work you can add constraints to your label using a SpringLayout. This allows you to position edges an exact distance from other edges, which by default also sorts the components size (By basically setting the edges a set distance apart when you lay it out) I have demonstrated below with a textArea, but is could easily apply to your label as well.
public class SO {
public static void main(String[] args) {
//Components
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setSize(frame.getSize());
JTextArea text = new JTextArea();
//Add components
panel.add(text);
frame.add(panel);
//Layout add & setup
SpringLayout layout = new SpringLayout();
panel.setLayout(layout);
layout.putConstraint(SpringLayout.WEST, text, 10, SpringLayout.WEST, panel);
layout.putConstraint(SpringLayout.NORTH, text, 10, SpringLayout.NORTH, panel);
layout.putConstraint(SpringLayout.EAST, text, -10, SpringLayout.EAST, panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
}
Although not recommended, you can do absolute positioning if you set your layout manager to null.
storePanel.setLayout(null);
// imageLabel initialization code
storePanel.add(imageLabel);
imageLabel.setBounds(20, 20, 50, 50);
Oracle Documentation
My advice is to use a Good IDE + UI Builder combo such as:
Netbeans GUI Builder
Eclipse WindowBuilder
IntelliJ GUI Designer
Thease are WYSIWYG tools that can generate Swing code using flexible Layout Managers such as Group Layout or JGoodies Form Layout.
A layout manager is a must if you want to design good UIs. They not only handle the size and positioning of components, but things such as redistributing / repositioning / resizing components on window resize (which is really hard to get right by hand). Also, those UI designers can hint you so that you stick to the guidelines and best practices in order to design high quality / cross-platform UI.
I want to reduce the size between the components with in the Formatting group (left side on the image). How to do this?
JPanel formattingGroup = createGroupWithName("Formatting");
formattingGroup.setMinimumSize(new Dimension(250, 20));
formattingGroup.setLayout(new GridLayout(5, 0));
add(formattingGroup);
final JCheckBox showSurface = new JCheckBox("Show surface");
showSurface.setSelected(true);
formattingGroup.add(showSurface);
final JCheckBox showTerrain = new JCheckBox("Show terrain");
showTerrain.setSelected(true);
formattingGroup.add(showTerrain);
final JCheckBox showVehicleStatus = new JCheckBox("Show vehicle status");
showVehicleStatus.setSelected(true);
formattingGroup.add(showVehicleStatus);
JPanel pnl = createGroupWithName("Depth Stretch");
formattingGroup.add(pnl);
JSlider slider = new JSlider(0, 10);
pnl.add(slider);
When using a GridLayout all components are made the same size.
You are adding a JPanel with a TitledBorder and a JSlider to the grid. Therefore the checkboxes will take the same vertical height as that panel.
You need to use a different layout manager for the panel. Maybe a vertical BoxLayout.
You might look at available size variants, discussed in Resizing a Component.
Use gridbaglayout because that gives you the opportunity to give weights, to columns or rows and set spacing and padding values.
I made a Swing application that contains out of 12 Frames and they all are made with GridBagLayout.
I also tried other before that but they all had limits. That's where the GridBagLayout kicks in. It's a bit harder in begin to understand how it works, but once you get feeling with it, it really is best thing to get the components where you want.
If you want i'll give you a cool example of a frame created with GridBagLayout.
I'm using some JTextArea in my Swing application. The surrounded JScrollPane is added to a JPanel using the GridBagLayout manager.
// Pseudo Code ----
JTextArea area = new JTextArea();
area.setRows(3);
JScrollPane sp = new JScrollPane(area);
JPanel p = new JPanel(new GridBagLayout());
p.add(sp, new GridBagConstraints(
0, 0, 1, 1, 1, 0, WEST, HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
// ----------------
Everything works fine. No problem at all until I will resize the JFrame. Then both JTextArea will collapse to one row. However there is enough place for at least one of them.
Why the element collapse to one row?
Does anyone know a solution? Has anyone an idea?
I believe this is because you have your weighty set to 0 (6th argument to the GridBagConstraints constructor). You'll need to increase this if you want your component to grow vertically.
Also make sure you are setting the 'preferred size' property on your scrollpane's. I've had strange behavior (panes/fields collapsing/disappearing) when frames and panels get resized when this property is not set.
If I use a BorderLayout around my elements, it works.
Pete, MrWiggles, Thank you for your help!!
I had a similar problem recently where I had two JTextAreas with different GridBagConstraint.weighty values and both were set to GridBagConstraint.fill = BOTH. When I would change the text in the JTextAreas, they would change sizes (which I would expect not to happen if weights and fill values are set). Oddly enough, all I had to do was set a preferred size to the JScrollPanes that surrounded the JTexAreas. The preferred size dimension could be anything, as the "fill = BOTH" caused the preferred size to be ignored, but it did something magical to fix my problem.