Java Swing BorderLayout make one region not resizable - java

I have a Java Swing GUI where the top level layout manager is BorderLayout. I'd like it so that when the user resizes my GUI below the preferred size the center region can't be resized any smaller (or at least takes precedence in resizing) and the north/south regions become smaller.
The way it's working right now is my north and south panels are taking precedence and blowing away my center region first. I've tried setting a minimum size on the center panel once it has all of its components added to it
centerPanel.setMinimumSize(centerPanel.getPreferredSize());
but that isn't working for me. It's still the first region to minimize on a resize.

Maybe a BoxLayout will work. Box layout will respect the minimum size of a component. See the section from the Swing tutorial on How to Use Box Layout for more information.

I don't think anything simpler than GridBagLayout will serve. BorderLayout is not good about honoring minimum sizes.

Related

A Flexible Layout manager that will change the layout according to resize

In my JPanel, I have 6 buttons laid out in a row (using FlowLayout as of now). The default size of the panel is enough to accommodate these buttons in one row. But, when the frame is resized it gets stuck at the size that is the sum of the minimum sizes of each button.
I need a layout manager that simply puts the buttons in a new row on re-sizing of the panel.
I'm pretty new to Java Swing so I apologize in advance if this is a trivial question.
MigLayout is by far the best layout manager I've ever used. Things that used to require nested containers and lots of hard to understand code can be done in a single container with simple to understand (and maintain) string constraints.
The flow layout is capable of your desired behavior (moving components into new row if they cannot fit). Check out the swing tutorial (run FlowLayoutDemo). You'll have to show us your source code to find out, whether there is some other constrain which prevents it.
FlowLayout does actually paint components on a new row, but the problem is that the preferred size of the panel doesn't change so in many cases you can't see the components (unless you happen to add the panel to the CENTER of a BorderLayout).
One solution is to use the Wrap Layout, which extends FlowLayout to recalculate the preferred size of the panel so that you see the buttons on a new row.

Using Layouts in Java

I have a JFrame with layout BorderLayout, I add JPanels using BorderLayout.CENTER
I have a JPanel(added using CENTER), that uses GridLayout to place 4 buttons.
These buttons are MASSIVE, taking up the whole screen. Or, I do it my way as follows:
I have a JFrame with layout null, I set JPanel bounds and add them.
I have a JPanel:
It sets it's own bounds so it takes up center 1/2 of screen, and is only 1/8 of the screen
tall.
It adds buttons using grid layout, and results in a nice line of buttons.
Obviously the second option looks better, but as I wish to conform to the norm, and always use layouts... How to I mix customization and layouts?(Or just solve my problem at all)
When you add a componeent to BorderLayout.CENTER, it will expand to fill the remaining space of the container not used by the other portions of the BorderLayout. Also, you can only add one component at a time to BorderLayout.CENTER. Subsequent adds will replace the previous component.
As for solving your exact problem, I suggest you start by taking a look at A Visual Guide to Layout Managers. This will give you a primer on what layouts are available in the Swing API. Oracle also has more in-depth tutorials for each layout. By nesting layouts, you can give your UI any look that you wish while leveraging their power, especially auto-calculations when a window is resized or otherwise changed.

Java swing - fill size

Is there a way to set, when specifying height and width of a component in Swing, that a given object should fill the available vertical/horizontal space? I.e. I would like to say setSize(*, 100) to allow horizontal fill.
You can call setSize with whatever you want, but in the end it is the LayoutManager of the parent Container which decides what position and what size each component gets.
So by using the correct LayoutManager you can typically succeed in letting a component take all the available width.
As you can see in the BorderLayout part of the Visual guide to LayoutManagers tutorial the PAGE_START and PAGE_END take all the available width.
By specifying the height as preferred size you will obtain the desired result
A BorderLayout is probably what you'll want to use, it allows you to set components to North, West, South, East and center.
So for horizontal fill use NORTH, for vertical fill use WEST and for both CENTER.

Dynamically resize JPanels to fit width of window

I've got an arbitrary number of JPanels being created based on user input (like 1-8 panels). Right now, I'm putting all the panels in a larger panel using FlowLayout, and then adding that panel to my main window which is using BoxLayout. I want the panels to fit the width of the main window but right now they are very small. Should I use a different layout or is there a way to do this?
You have to choose GridLayout or GridBagLayout.
Yes, you should use a different layout manager. Use BorderLayout (tutorial here), which streches all the contents to fit the container.
Also, BorderLayout doesn't allow more than one component in each area, thus you will need another sub-panel to hold your panels. Don't use FlowLayout for that sub-panel, as it will not have the streching behaviour your are looking for.

Dynamic resize of Layout Manager areas

In which Swing layout manager it is possible to change layout areas programmatically? And how to do this with lowest cost?
I have to create component with functionality similar to JSplitPane but with three panels from scratch. One of the moments is to Expand/Collapse one of the panels after clicking oneTouchExpandable button on the divider. But the problem is that I don't know how to implement this collapse action. I tried just setting panels width to 0, but the layout area which contains this panel doesn't shrink after the component. I tried to do this in all Layout Managers, but effect is the same.
Thanks.
When making a change that affects the layout of a panel after the GUI is visible you need to revalidate() the panel which essentially invoke the layout on the panel. In your case it might be easier to simply make the component invisible:
component.setVisible(false);
panel.revalidate();
panel.repaint(); // this is only required sometimes
All layout managers resize dynamically. However, the width and height properties are the result of the layouting, and will be overwritten.
The properties you should look at are preferredSize, minimumSize, and maximumSize - the layout managers base their calculations on those properties, though the exact effect depends on the layout manager (e.g. BorderLayout will give the NORTH, SOUTH, WEST and EAST components their preferred size if possibe and assign the remainder to the CENTER component).
Once you've changed the size properties, you have to call revalidate() on the container, then you should see the changes.
I'm with the revalidate()/preferredSize answers but just wanted to suggest this: don't re-invent the wheel! Use the JideSplitPane (part of JIDE's free "Common Layer") - it supports more than two splits.
Thanks to all for the answers. Finally I ended up with combining solutions from several answers.
My final solution is following:
I use BorderLayout, set West, Center and East panels and then manipulate their sizes by setting PreferredSize to West and East panels. The scheme of rendering is following: while laying out the components BorderLayout gives East and West panels their PreferredSize and rest of the space to Center panel. So with a bit of easy calculations I can manipulate size of each of three panels painlessly.
I also added dividers(originally just JPanel components with fixed size) to West and East panels(their size is also considered while calculating). For dynamic resize I handle dragging events on this dividers and recalculate panel sizes.
Refreshing is done with following snippet:
container.setVisible(false);
container.revalidate();
container.repaint();
container.setVisible(true);
I'd like to put this code somewhere to be available for others, but don't know where exactly to do this. So if you know such place, please point me to it in the comments.

Categories

Resources