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.
Related
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!
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.
I have a JPanel that contains a bunch of small icons, and a JLabel containing a bigger icon.
First of all, I need clarification on something. By not setting panel.isOpaque, the said panel would have a transparent background and would properly overlap the icons of my JPanel and JLabel. Is this true?
Now to my problem. I've been following the LayeredPanes tutorial on the Oracle website, and I can't seem to make it right on my case.
JFrame window = new JFrame();
ImageIcon underIcon;
URL urlUnder = myClass.class.getResource("images/underImage.gif");
underIcon = new ImageIcon(urlUnder);
JLabel labelUnder = new JLabel(underIcon);
ImageIcon panelIcon;
URL urlAbove = myClass.class.getResource("images/aboveImage.gif");
panelIcon = new ImageIcon(urlAbove);
JLabel aboveIcon1 = new JLabel(panelIcon);
JLabel aboveIcon2 = new JLabel(panelIcon);
JPanel panelAbove = new JPanel(new BorderLayout());
panelAbove.setOpaque(false);
panelAbove.add(aboveIcon1, BorderLayout.WEST);
panelAbove.add(aboveIcon2, BorderLayout.EAST);
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setLayout(new BorderLayout());
layeredPane.add(labelUnder, BorderLayout.CENTER, 1);
layeredPane.add(panelAbove, BorderLayout.CENTER, 2);
layeredPane.setOpaque(true);
window.setContentPane(layeredPane);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);
I only see the contents of the panel. And I'm 100% sure the images are there on getResource, so that's not the issue. Please advice on how to properly use Layered Panes.
The problem is you are setting a layout manager to the JLayeredPane
layeredPane.setLayout(new BorderLayout());
In of it self, this is not a problem, but your choice of layout manager is.
BorderLayout will only a single componet to occupy any of it's 5 predefined positions. This means when you add your second component, it, effectively, replaces the first.
Try using someone like GridBagLayout instead. Providing a single GridBagConstaint set so that the weightx/y values ara equal to 1, the fill property is set to BOTH and it's gridx/y properties are set to 0
Unlike BorderLayout, GridBagLayout will allow you to layout components to the same position
From the Java Tutorial:
layeredPane.add(dukeLabel, new Integer(2), 0);
This code uses the three-argument version of the add method. The third argument specifies the Duke label position within its depth, which determines the component's relationship with other components at the same depth.
Positions are specified with an int between -1 and (n - 1), where n is the number of components at the depth. Unlike layer numbers, the smaller the position number, the higher the component within its depth. Using -1 is the same as using n - 1; it indicates the bottom-most position. Using 0 specifies that the component should be in the top-most position within its depth. As the following figure shows, with the exception of -1, a lower position number indicates a higher position within a depth.
So your depth orders are the wrong way around, also start from 0.
I also found this in the Solving Common Component Problems Section
Problem: The components in my layered pane are not layered correctly. In fact, the layers seem to be inversed — the lower the depth the higher the component.
This can happen if you use an int instead of an Integer when adding components to a layered pane. To see what happens, in the LayeredPaneDemo class, change
layeredPane.add(label, new Integer(i));
to
layeredPane.add(label, i);.
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 have a small "popup" like this:
But I don't want the padding around the button, I want it to be as small as it can be with the supplied text.
btn.setMargin(new Insets(1, 1, 1, 1));
panel.add(lbl, "wrap");
panel.add(btn);
frame.pack();
frame.setVisible(true);
At least this doesn't work...
Can this be achieved on MigLayout or should I use some other layout manager for this frame.
What's your MigLayout constraints that it was built with? You might want to try using novisualpadding if you aren't already. Also, the debug layout constraint will draw boxes around your components to show what room they take up. (I think the red dotted lines are the size of the components and the blue dotted lines are the "cells" that the component is in.)
// old version
// JPanel panel = new JPanel(new MigLayout());
// new verion
JPanel panel = new JPanel(new MigLayout("debug, novisualpadding"));
I use MigLayout pretty often and have found the "cheat sheet" pretty useful. http://migcalendar.com/miglayout/cheatsheet.html
A layout manager should not affect the way a component is painted.
The setMargin(...) works fine for me when using the Metal LAF. Maybe your LAF doesn't support the setMargin() method. Or maybe you have some code elsewhere that is overriding the preferred size of the button causing it to paint like this.
However, if the MIG layout turns out to be the problem, you could try the Wrap Layout.
Taking MIke's answer as a startup, I found in the MIG "CheatSheet" a possible solution to your problem.
When you set up a MIGLayout, you can specify the gap between component with an integer between the square brackets defining columns and rows.
E.g.
MigLayout buttonMig = new MigLayout("", "[139px,grow]0[179px,grow]50[142px,grow][143px,grow]", "0[60px:60px:60px,center]");
I've just been having this issue too. I discovered that the following worked for me:
this.add(okButton, "width pref:pref:pref");
or
this.add(okButton, "wmax pref");
Also when using the substance look and feel there is a feature where the minimum size is always too wide. This can be overridden with this obscure hack.
okButton.putClientProperty(
SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY, Boolean.TRUE);