Nested JPanel resizing problem - java

I have two JPanels (let's call these Panel1 and Panel2). These panels are of the same width, but varying heights.
I want to put these JPanels into one big JPanel (lets call it Panel0), and stack them on top of each other (I decided to set Panel0's layout as GridLayout(0,1)).
The problem, is that both nested panels (panels 1 and 2) end up having the same dimensions (those of the biggest between the two), instead of the setPreferredDimension and setDimension that I set to them.
Sorry, I can't really provide any code (there's a lot of crap added to the panel's, and it's all for something work-related). Any advice? Thanks!

GridLayout forces all components to be the same size; that's why it's called a grid.
Since you only have two panels, I'd suggest using a BorderLayout with one panel at NORTH and the other CENTER. If you allow resizing, then the one in CENTER will be the expand to fill any extra vertical space, so just be aware of that.

Related

How can I go about creating this design with Java's Swing GUI tools?

This is a mock up for what I have in mind as a layout for my project:
The way I tried to accomplish this is:
I set the entire frame to a border layout and then cut it horizontally with two panels, we'll call them north and south panels. The south panel is Panel 3 from the first picture.
I set the north panel to a border layout as well and cut it vertically with two panels. These become panel 1 and panel 2 in the first picture. The problem occurs when I try to resize the window. I would like the panels to scale proportionally to eachother so the size ratio's between the panels stay the same. The problem is, instead of resizing, the panels just move away from each other like so:
Any ideas for creating the desired design? Am I on the right track or is there another swing layout that is better suited to my needs?
I would like the panels to scale proportionally to eachother so the size ratio's between the panels stay the same.
Try using a horizontal BoxLayout. I believe it will allocate extra space proportionally up to the components maximum size if extra space is available.
Or if that doesn't work you can use a GridBagLayout. You can use the weightx constraint for each component you add to the panel. This will control how much extra space is given to each component.
Read the section from the Swing tutorial on Layout Managers for working example of each.

Advise on Java GUI Component Layout strategy

I am hoping someone can offer a strategy for the following Java GUI:
I am implementing a Scrabble-like algorithm and I would like to write a GUI where a user can compete with the algorithm. My experience with GUIs is limited and I am trying to avoid a big learning curve if someone can suggest a useful subset of components upon which I can focus.
I would like to display two playing areas side by side. Each playing area contains a board and a tile holder. Tiles from the holder can be dragged and dropped onto the board.
Obviously, the basic component is the tile, which is just a square displaying a letter. The tile holder and the board are both tile containers (grids of different sizes). The playing areas each hold the two tile containers and allow dragging and dropping from one container to the other.
The layout of the two playing areas is: the board on top, the tile holder on the bottom, and some neutral space between them.
The layout for the window is just to display the two playing areas side by side.
Perhaps naively, it seems to me I don't need much. But finding the right pieces is proving to be quite a task.
Any advice is appreciated.
Top level JPanel with a GridLayout, 1 row, 2 columns, will create for you a panel with two evenly split areas. After that you can add another JPanel for each side (just sequentially add them), and these two JPanels can have a BorderLayout. For these two BorderLayout JPanels, you can add to each the following:
A JPanel with a FlowLayout of ImageIcons that hold a pictures of a scrabble tile, and this JPanel will be added to the south position on the BorderLayout JPanel.
Another JPanel with a custom class you'll make called ScrabbleBoard extends JComponent. Here you can extend paintComponent and draw the board how you wish, probably making use of obtaining the width and height so you can draw a board that scales to how much space you have available for the component. This custom JComponent will be added to the center position of the BorderLayout JPanel.
A component added to the center position of a BorderLayout tries to be greedy and takes up as much room as possible, while components on the sides do not, so it's often a good choice for UI's that require a small navigation or menu control area, and a larger area to view what is considered the main graphics.

How to make BoxLayout behave as vertical FlowLayout?

FlowLayout performs "pressure" from the right, so as all components are trying to take their minimal widths. Contrary, BoxLayout tries to spread all components to fill entire height of the space.
Can I add some filler as last component or something to make all components have minimal heights in BoxLayout?
You could use Box.createGlue(), which returns a component that takes up as much space as the BoxLayout will give it. Adding it to the bottom of a vertical BoxLayout will scrunch the other components to the top.
You could also use nested layouts.

Why is the setPrefferedSize() method not working for JPanel?

I have created n JPanels and in each JPanel I have added 3 components. I added these JPanels to a new JPanel as rows. The layout for the n JPanels is FlowLayout and for the main panel is BorderLayout. The setPrefferedSize() method is working fine for the components which I have added in the n JPanels but it is not working for the n JPanels.
I am trying npanels[i].setPrefferedSize(new Dimension(300,25)),
I want the height of the JPanel to be equal to height the components added in it (which is 25).
Is there any constraint that the height of a JPanel should be some minimum value?
Please help I tried a lot of things but it's not working.....
Some layout managers tend to ignore the size setting...
Read somewhere that BorderLayout might tend to ignore the width for NORTH and SOUTH components,
height for EAST and WEST,
both height and width are ignored for CENTER...
Could this be the case?
Also, can you provide a screenshot or a diagram explaining whats happening?
The setPrefferedSize() method is
working fine for the components
There is generally no need to set a preferred size for components. Swing will calculate the preferred size automatically.
layout for n JPanels is FlowLayout...
which i have added in n JPanels but it
is not working for n JPanels
Again, there is no need to set the preferred size of each panel. The size will be calculated automatically based on the preferred size of all the components.
the main panel is BorderLayout
This does not make sense since you can't add "n" panels to the BorderLayout. You can only add one component to the North,Center and South so you can have a maximum of 3 different vertically display panels. In this case if you use frame.pack() then each panel will be displayed at its preferred size. On the other hand if you use frame.setSize(300, 400) then the hieght of the Center panel will be stretched.
Since it appears you want all panels the same size maybe you should be using a GridLayout, otherwise you can try a BoxLayout. Read the Swing tutorial. It explains all about using the layout managers.
If you need more help post your SSCCE.

JPanel size by inner components

Is it possible to tell JPanel to set its size to fit all components that it contains? Something like pack() for JFrame.
edit: The trick with preferredSize didn't help. I've got JSplitPane, where in one part there is GridBagLayout with many labels (see screenshot) and labels overlap each other.
screenshot http://foto.darth.cz/pictures/screen.png
After looking at the source code for pack(), I came up with:
panel.setPreferredSize(panel.getPreferredSize());
This forces the panel to recalculate its preferred size based on the preferred sizes of its subcomponenents.
You may or may not have to call validate() afterward; in my tiny example, it seemed to make no difference, but the Javadoc says:
The validate method is used to cause a container to lay out its subcomponents again. It should be invoked when this container's subcomponents are modified (added to or removed from the container, or layout-related information changed) after the container has been displayed.
So I guess it depends on why you're having to repack your JPanel.
By default Containers have a preferred size that matches the preferred layout size given by the container. So literally all you have to do is:
panel.setSize(panel.getPreferredSize());
Presumably you are doing something odd with the parent to stop the parent's layout manager doing the equivalent of this.
maybe you can do something like that by removing from your panel
setResizable(false);
I would try:
panel.revalidate();
panel.repaint();
This will not necessarily set the panel to its preferred size, that is more dependent on what the layout manager decides to use.
This is useful in cases where you have added/removed components from a panel that is currently displayed and visible.
Update:
Based on your screenshot I can say the following:
1) Consider programatically changing the divider location.
2) Consider programatically resizing the window itself horizontally since it seems to be a little tight to show both sides of the split pane.
Or both.
You can set the divider location by doing
splitPane.setDividerLocation(newSize);
Keep in mind that there are two overloaded methods for this, one taking a float one taking an int. The float does a percentage of the size while the int is the size in pixels. The size is for the left hand panel (or top panel for that orientation).
I would consider possibly changing the divider location based on the preferred width of the panels.
The javax.swing mysteries reveal themselves only gradually, and only to those who are prepared to offer many libations (particularly torn out clumps of hair, hours burning the midnight oil, etc.) to the gods of Swing.
However, for this case in point I would suggest the following as a sort of Swiss army knife which usually does what you think the framework should do anyway:
myJPanel.getTopLevelAncestor().validate()
As the sacred text says, "Validates this container and all of its subcomponents." (Container.validate). NB getTopLevelAncestor() is a JComponent method.
Can't remember how JSplitPane fits into this: try it and you'll probably find that it validates both components (right and left, top and bottom), but I would be surprised if changing the divider doesn't do this for you anyway.
I had a similar issue using Netbeans GUI Builder. My inner panels were getting weird sizes; I was trying to adjust the minimum and preferred sizes manually, which was a frustrating exercise.
The problem was solved when I reset all the minimum and preferred sizes back to default (In Netbeans GUI Builder: right click JPanel component -> Properties -> preferredSize -> Reset to Default). When there is no imposed size, the jpanel takes the size of the inner component.
Note: GridBaLayout was used in my case
JSplitPanes are a bit fussy when it comes to its children's sizes, have a look at the Java tutorial. Are you using the GridBagLayout correctly? Looks like it's not setting the right JPanel's minimum size properly.
Here's an example of a panel which:
Resizes with it's parent.
Sets the width to the width of the parent.
Sets the height according to sum of the height of all of it's children.
JPanel panel = JPanel(new GridBagLayout())
panel.setMaximumSize(new Dimension(panel.getMaximumSize().width, panel.getPreferredSize().height))
panel.validate()
panel.repaint()

Categories