Simple BorderLayout problem

F

Fencer

Hello, I have a problem with BorderLayout, and I bet it's really simple.
I have JPanel with a TitledBorder (like a "group" widget) and this
JPanel contains a button.

Now I want to displays this JPanel centered horizontally and vertically
and I don't want it to occupy all the space of the client area of the
JFrame.

I tried this:
package main;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

public class CenteredGroup {

CenteredGroup() {
frame.setSize(1024, 768);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel contentPane = (JPanel)frame.getContentPane();

BorderLayout borderLayout = new BorderLayout(50, 50);

frame.setLayout(borderLayout);

contentPane.setLayout(borderLayout);

JPanel groupPanel = new JPanel();

groupPanel.setBorder(new TitledBorder("This is my group text."));

JButton button = new JButton("A button");

groupPanel.add(button);

contentPane.add(groupPanel, BorderLayout.CENTER);

frame.setVisible(true);
}

public static void main(String[] args) {
new CenteredGroup();
}

JFrame frame = new JFrame("Centered Group");
}

However, the "group control" occupies the entire client area of the
frame. Why?

I can provide a screenshot of what it looks like and how I want it to
look like if you have trouble understanding my problem description.

- F
 
R

RedGrittyBrick

Hello, I have a problem with BorderLayout, and I bet it's really simple.
I have JPanel with a TitledBorder (like a "group" widget) and this
JPanel contains a button.

Now I want to displays this JPanel centered horizontally and vertically
and I don't want it to occupy all the space of the client area of the
JFrame.

I tried this:
package main;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

public class CenteredGroup {

CenteredGroup() {
frame.setSize(1024, 768);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel contentPane = (JPanel)frame.getContentPane();

BorderLayout borderLayout = new BorderLayout(50, 50);

frame.setLayout(borderLayout);

contentPane.setLayout(borderLayout);

JPanel groupPanel = new JPanel();

groupPanel.setBorder(new TitledBorder("This is my group text."));

JButton button = new JButton("A button");

groupPanel.add(button);

contentPane.add(groupPanel, BorderLayout.CENTER);

frame.setVisible(true);
}

public static void main(String[] args) {
new CenteredGroup();
}

JFrame frame = new JFrame("Centered Group");
}

However, the "group control" occupies the entire client area of the
frame. Why?

Because that is the defined behaviour of BorderLayout. If you don't want
that behaviour it is best to not use BorderLayout.

http://java.sun.com/javase/6/docs/api/java/awt/BorderLayout.html


You might like to read the tutorials and try some other layout managers

http://java.sun.com/docs/books/tutorial/uiswing/layout/visual.html
http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html


GridBagLayout is notoriously hard to understand. Many experienced Java
Developers feel it is worthwhile getting to know it well.

I've often seen it asserted that it is surprisingly easy to write your
own layout manager.

I'd recommend you also try a third party layout manager like MigLayout.
 
K

Knute Johnson

Hello, I have a problem with BorderLayout, and I bet it's really simple.
I have JPanel with a TitledBorder (like a "group" widget) and this
JPanel contains a button.

Now I want to displays this JPanel centered horizontally and vertically
and I don't want it to occupy all the space of the client area of the
JFrame.

I tried this:
package main;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

public class CenteredGroup {

CenteredGroup() {
frame.setSize(1024, 768);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel contentPane = (JPanel)frame.getContentPane();

BorderLayout borderLayout = new BorderLayout(50, 50);

frame.setLayout(borderLayout);

contentPane.setLayout(borderLayout);

There is no need to set both the JFrame layout and the ContentPane layout.
JPanel groupPanel = new JPanel();

groupPanel.setBorder(new TitledBorder("This is my group text."));

JButton button = new JButton("A button");

groupPanel.add(button);

contentPane.add(groupPanel, BorderLayout.CENTER);

frame.setVisible(true);
}

public static void main(String[] args) {
new CenteredGroup();
}

JFrame frame = new JFrame("Centered Group");
}

A little indentation would be nice.
However, the "group control" occupies the entire client area of the
frame. Why?

I can provide a screenshot of what it looks like and how I want it to
look like if you have trouble understanding my problem description.

- F

BorderLayout causes the components added to it to fill the available
area. Specifying the hgap and vgap just put extra space between
components not the outer edges. Use a layout that will not do that such
as GridBagLayout. GBL also has the ability to adjust the size and
positions of components.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test8 extends JPanel {
public test8() {
setPreferredSize(new Dimension(40,30));
setBackground(Color.BLUE);
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridBagLayout());
test8 t8 = new test8();
f.add(t8);
f.setSize(400,300);
f.setVisible(true);
}
});
}
}

And this one is a button centered in a JPanel, centered in the JFrame.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test9 extends JPanel {
public test9() {
super(new GridBagLayout());
setPreferredSize(new Dimension(160,120));
JButton b = new JButton("Press Me");
add(b);
setBorder(BorderFactory.createLineBorder(Color.BLUE,10));
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridBagLayout());
test9 t9 = new test9();
f.add(t9);
f.setSize(800,600);
f.setVisible(true);
}
});
}
}

It is trivial with GBL to align the JPanel to the upper left corner of
the JFrame.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test9 extends JPanel {
public test9() {
super(new GridBagLayout());
setPreferredSize(new Dimension(160,120));
JButton b = new JButton("Press Me");
add(b);
setBorder(BorderFactory.createLineBorder(Color.BLUE,10));
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.weightx = c.weighty = 1.0;

test9 t9 = new test9();
f.add(t9,c);
f.setSize(800,600);
f.setVisible(true);
}
});
}
}
 
L

Lew

Fencer said:
... problem with BorderLayout ...
I have JPanel with a TitledBorder (like a "group" widget) and this
JPanel contains a button.

Now I want to displays this JPanel centered horizontally and vertically
and I don't want it to occupy all the space of the client area of the
JFrame.

I tried this [indentation restored from original post - LB]:
package main;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

public class CenteredGroup {

CenteredGroup() {
frame.setSize(1024, 768);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel contentPane = (JPanel)frame.getContentPane();

BorderLayout borderLayout = new BorderLayout(50, 50);

frame.setLayout(borderLayout);

contentPane.setLayout(borderLayout);

JPanel groupPanel = new JPanel();

groupPanel.setBorder(new TitledBorder("This is my group text."));

JButton button = new JButton("A button");

groupPanel.add(button);

contentPane.add(groupPanel, BorderLayout.CENTER);

frame.setVisible(true);
}

public static void main(String[] args) {
new CenteredGroup();
}

JFrame frame = new JFrame("Centered Group");

Sorry, but the placement of this declaration and initialization in the source
is confusing
Because that is the defined behaviour of BorderLayout. If you don't want
that behaviour it is best to not use BorderLayout.

<http://java.sun.com/javase/6/docs/api/java/awt/BorderLayout.html >

You might like to read the tutorials and try some other layout managers

<http://java.sun.com/docs/books/tutorial/uiswing/layout/visual.html>
<http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html>

GridBagLayout is notoriously hard to understand. Many experienced Java
Developers feel it is worthwhile getting to know it well.

I've often seen it asserted that it is surprisingly easy to write your
own layout manager.

I'd recommend you also try a third party layout manager like MigLayout.

Side notes, OP: Do your GUI on the EDT only. Remember to 'pack()'. I suggest
doing the 'setVisible()' outside the constructor. Package-private access
isn't bad, but I wonder why you chose it over private access.
 
M

markspace

Fencer said:
However, the "group control" occupies the entire client area of the
frame. Why?


Basically as others have said: it's because BorderLayout and JPanel
where designed to work that way. Both want to expand components to fill
all available space.

The advice you've got on this thread so far is good. Just to add a bit
of perspective ("there's more than one way to do it"), I feel that when
you start wanting to put GUI components in just the right spot in a
layout, it's time to get a drag-and-drop editor and do it the easy way.

NetBeans has a great GUI editor. Download it, layout your panel (or
JFrame) the way you like, and you're done. It's good to learn exactly
how to manipulate the GUI components programatically by using
GridBagLayout or whatnot, but it's often not necessary to do so. The
GUI editor will work in 90% or more of your use cases.

http://netbeans.org/

http://netbeans.org/kb/docs/java/quickstart-gui.html
 
F

Fencer

On 2010-02-15 17:50, Fencer wrote:
[snip my OP]

Thanks for your replies. I've decided to take a look at GridBagLayout as
suggested. Since I'm a layout-newbie I wanted to be able to print the
state of a GridBagConstraints object, so I wrote this helper class:

package main;

import java.awt.GridBagConstraints;

public class PrintGridBagConstraints {

public static void print(GridBagConstraints gbc) {
String out = "";

out += "gridx: " + (gbc.gridx == GridBagConstraints.RELATIVE ?
"RELATIVE" : gbc.gridx) + "\n";
out += "gridy: " + (gbc.gridy == GridBagConstraints.RELATIVE ?
"RELATIVE" : gbc.gridy) + "\n";
out += "gridwidth: " + getGridHeightOrWidth(gbc.gridwidth) + "\n";
out += "gridheight: " + getGridHeightOrWidth(gbc.gridheight) + "\n";
out += "weightx: " + gbc.weightx + "\n";
out += "weighty: " + gbc.weighty + "\n";
out += "anchor: " + getAnchor(gbc.anchor) + "\n";
out += "fill: " + Fill.fromInt(gbc.fill).toString() + "\n";

System.out.print(out);
}

private static String getAnchor(int anchor) {
Anchor a = Anchor.fromInt(anchor);

if (a == Anchor.UNDEFINED) {
return anchor + " - undefined";
}
else {
return a.toString();
}
}

private static String getGridHeightOrWidth(int heightOrWidth) {
if (heightOrWidth == GridBagConstraints.RELATIVE) {
return "RELATIVE";
}
else if (heightOrWidth == GridBagConstraints.REMAINDER) {
return "REMAINDER";
}
else {
return Integer.toString(heightOrWidth);
}
}

/*
* There are three kinds of possible values: orientation relative,
baseline relative and absolute.
* Orientation relative values are interpreted relative to the
container's component orientation
* property, baseline relative values are interpreted relative to
the baseline and absolute
* values are not.
* The absolute values are: CENTER, NORTH, NORTHEAST, EAST,
SOUTHEAST, SOUTH, SOUTHWEST, WEST,
* and NORTHWEST.
* The orientation relative values are: PAGE_START, PAGE_END,
LINE_START, LINE_END,
* FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_START and LAST_LINE_END.
* The baseline relvative values are: BASELINE, BASELINE_LEADING,
BASELINE_TRAILING, ABOVE_BASELINE,
* ABOVE_BASELINE_LEADING, ABOVE_BASELINE_TRAILING, BELOW_BASELINE,
BELOW_BASELINE_LEADING, and
* BELOW_BASELINE_TRAILING. The default value is CENTER.
*/
enum Anchor {
/* Absolute values start. */
CENTER(GridBagConstraints.CENTER, "Absolute"),
NORTH(GridBagConstraints.NORTH, "Absolute"),
NORTHEAST(GridBagConstraints.NORTHEAST, "Absolute"),
EAST(GridBagConstraints.EAST, "Absolute"),
SOUTHEAST(GridBagConstraints.SOUTHEAST, "Absolute"),
SOUTH(GridBagConstraints.SOUTH, "Absolute"),
SOUTHWEST(GridBagConstraints.SOUTHWEST, "Absolute"),
WEST(GridBagConstraints.WEST, "Absolute"),
NORTHWEST(GridBagConstraints.NORTHWEST, "Absolute"),
/* Absolute values end. */

/* Orientation relative values start. */
PAGE_START(GridBagConstraints.PAGE_START, "Orientation relative"),
PAGE_END(GridBagConstraints.PAGE_END, "Orientation relative"),
LINE_START(GridBagConstraints.LINE_START, "Orientation relative"),
LINE_END(GridBagConstraints.LINE_END, "Orientation relative"),
FIRST_LINE_START(GridBagConstraints.FIRST_LINE_START,
"Orientation relative"),
FIRST_LINE_END(GridBagConstraints.FIRST_LINE_END, "Orientation
relative"),
LAST_LINE_START(GridBagConstraints.LAST_LINE_START,
"Orientation relative"),
LAST_LINE_END(GridBagConstraints.LAST_LINE_END, "Orientation
relative"),
/* Orientation relative values end. */

/* Baseline relative values start. */
BASELINE(GridBagConstraints.BASELINE, "Baseline relative"),
BASELINE_LEADING(GridBagConstraints.BASELINE_LEADING,
"Baseline relative"),
BASELINE_TRAILING(GridBagConstraints.ABOVE_BASELINE_TRAILING,
"Baseline relative"),
ABOVE_BASELINE(GridBagConstraints.ABOVE_BASELINE, "Baseline
relative"),

ABOVE_BASELINE_LEADING(GridBagConstraints.ABOVE_BASELINE_LEADING,
"Baseline relative"),

ABOVE_BASELINE_TRAILING(GridBagConstraints.ABOVE_BASELINE_TRAILING,
"Baseline relative"),
BELOW_BASELINE(GridBagConstraints.BELOW_BASELINE, "Baseline
relative"),

BELOW_BASELINE_LEADING(GridBagConstraints.BELOW_BASELINE_LEADING,
"Baseline relative"),

BELOW_BASELINE_TRAILING(GridBagConstraints.BELOW_BASELINE_TRAILING,
"Baseline relative"),
/* Baseline relative values end. */

UNDEFINED(-1337, "");

public static Anchor fromInt(int value) {
for (Anchor a : Anchor.values()) {
if (a.ordinal() == value) {
return a;
}
}

return Anchor.UNDEFINED;
}

@Override
public String toString() {
return this.name() + " - " + type;
}

private Anchor(int value, String type) {
this.type = type;
}

private String type;
}

enum Fill {
NONE(GridBagConstraints.NONE),
HORIZONTAL(GridBagConstraints.HORIZONTAL),
VERTICAL(GridBagConstraints.VERTICAL),
BOTH(GridBagConstraints.BOTH),

UNDEFINED(-1337);

public static Fill fromInt(int value) {
for (Fill f : Fill.values()) {
if (f.ordinal() == value) {
return f;
}
}

return Fill.UNDEFINED;
}

private Fill(int value) {
}
}
}

Was there an easier way to do that instead of writing that code? :)

The output from the public static print method() can look like:
gridx: RELATIVE
gridy: RELATIVE
gridwidth: REMAINDER
gridheight: 1
weightx: 0.0
weighty: 0.0
anchor: ABOVE_BASELINE - Baseline relative
fill: VERTICAL

Btw, I found a spelling error in the official documentation when writing
that code (that exists in the docs for both java 6 and 7). The word
relvative appears under the description of the anchor field (I've
retained it in my comment of my Anchor enum).

Armed with this helper class I will now try to work GridBagLayout work
as I want it. I have another control I want place in a particular place
apart from the centered JPanel in my OP. I will post back if I can't
make it work.

- F
 
K

Knute Johnson

On 2010-02-15 17:50, Fencer wrote:
[snip my OP]

Thanks for your replies. I've decided to take a look at GridBagLayout as
suggested. Since I'm a layout-newbie I wanted to be able to print the
state of a GridBagConstraints object, so I wrote this helper class:

package main;

import java.awt.GridBagConstraints;

public class PrintGridBagConstraints {

public static void print(GridBagConstraints gbc) {
String out = "";

out += "gridx: " + (gbc.gridx == GridBagConstraints.RELATIVE ?
"RELATIVE" : gbc.gridx) + "\n";
out += "gridy: " + (gbc.gridy == GridBagConstraints.RELATIVE ?
"RELATIVE" : gbc.gridy) + "\n";
out += "gridwidth: " + getGridHeightOrWidth(gbc.gridwidth) + "\n";
out += "gridheight: " + getGridHeightOrWidth(gbc.gridheight) + "\n";
out += "weightx: " + gbc.weightx + "\n";
out += "weighty: " + gbc.weighty + "\n";
out += "anchor: " + getAnchor(gbc.anchor) + "\n";
out += "fill: " + Fill.fromInt(gbc.fill).toString() + "\n";

System.out.print(out);
}

private static String getAnchor(int anchor) {
Anchor a = Anchor.fromInt(anchor);

if (a == Anchor.UNDEFINED) {
return anchor + " - undefined";
}
else {
return a.toString();
}
}

private static String getGridHeightOrWidth(int heightOrWidth) {
if (heightOrWidth == GridBagConstraints.RELATIVE) {
return "RELATIVE";
}
else if (heightOrWidth == GridBagConstraints.REMAINDER) {
return "REMAINDER";
}
else {
return Integer.toString(heightOrWidth);
}
}

/*
* There are three kinds of possible values: orientation relative,
baseline relative and absolute.
* Orientation relative values are interpreted relative to the
container's component orientation
* property, baseline relative values are interpreted relative to the
baseline and absolute
* values are not.
* The absolute values are: CENTER, NORTH, NORTHEAST, EAST, SOUTHEAST,
SOUTH, SOUTHWEST, WEST,
* and NORTHWEST.
* The orientation relative values are: PAGE_START, PAGE_END, LINE_START,
LINE_END,
* FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_START and LAST_LINE_END.
* The baseline relvative values are: BASELINE, BASELINE_LEADING,
BASELINE_TRAILING, ABOVE_BASELINE,
* ABOVE_BASELINE_LEADING, ABOVE_BASELINE_TRAILING, BELOW_BASELINE,
BELOW_BASELINE_LEADING, and
* BELOW_BASELINE_TRAILING. The default value is CENTER.
*/
enum Anchor {
/* Absolute values start. */
CENTER(GridBagConstraints.CENTER, "Absolute"),
NORTH(GridBagConstraints.NORTH, "Absolute"),
NORTHEAST(GridBagConstraints.NORTHEAST, "Absolute"),
EAST(GridBagConstraints.EAST, "Absolute"),
SOUTHEAST(GridBagConstraints.SOUTHEAST, "Absolute"),
SOUTH(GridBagConstraints.SOUTH, "Absolute"),
SOUTHWEST(GridBagConstraints.SOUTHWEST, "Absolute"),
WEST(GridBagConstraints.WEST, "Absolute"),
NORTHWEST(GridBagConstraints.NORTHWEST, "Absolute"),
/* Absolute values end. */

/* Orientation relative values start. */
PAGE_START(GridBagConstraints.PAGE_START, "Orientation relative"),
PAGE_END(GridBagConstraints.PAGE_END, "Orientation relative"),
LINE_START(GridBagConstraints.LINE_START, "Orientation relative"),
LINE_END(GridBagConstraints.LINE_END, "Orientation relative"),
FIRST_LINE_START(GridBagConstraints.FIRST_LINE_START, "Orientation
relative"),
FIRST_LINE_END(GridBagConstraints.FIRST_LINE_END, "Orientation relative"),
LAST_LINE_START(GridBagConstraints.LAST_LINE_START, "Orientation
relative"),
LAST_LINE_END(GridBagConstraints.LAST_LINE_END, "Orientation relative"),
/* Orientation relative values end. */

/* Baseline relative values start. */
BASELINE(GridBagConstraints.BASELINE, "Baseline relative"),
BASELINE_LEADING(GridBagConstraints.BASELINE_LEADING, "Baseline relative"),
BASELINE_TRAILING(GridBagConstraints.ABOVE_BASELINE_TRAILING, "Baseline
relative"),
ABOVE_BASELINE(GridBagConstraints.ABOVE_BASELINE, "Baseline relative"),

ABOVE_BASELINE_LEADING(GridBagConstraints.ABOVE_BASELINE_LEADING,
"Baseline relative"),

ABOVE_BASELINE_TRAILING(GridBagConstraints.ABOVE_BASELINE_TRAILING,
"Baseline relative"),
BELOW_BASELINE(GridBagConstraints.BELOW_BASELINE, "Baseline relative"),

BELOW_BASELINE_LEADING(GridBagConstraints.BELOW_BASELINE_LEADING,
"Baseline relative"),

BELOW_BASELINE_TRAILING(GridBagConstraints.BELOW_BASELINE_TRAILING,
"Baseline relative"),
/* Baseline relative values end. */

UNDEFINED(-1337, "");

public static Anchor fromInt(int value) {
for (Anchor a : Anchor.values()) {
if (a.ordinal() == value) {
return a;
}
}

return Anchor.UNDEFINED;
}

@Override
public String toString() {
return this.name() + " - " + type;
}

private Anchor(int value, String type) {
this.type = type;
}

private String type;
}

enum Fill {
NONE(GridBagConstraints.NONE),
HORIZONTAL(GridBagConstraints.HORIZONTAL),
VERTICAL(GridBagConstraints.VERTICAL),
BOTH(GridBagConstraints.BOTH),

UNDEFINED(-1337);

public static Fill fromInt(int value) {
for (Fill f : Fill.values()) {
if (f.ordinal() == value) {
return f;
}
}

return Fill.UNDEFINED;
}

private Fill(int value) {
}
}
}

Was there an easier way to do that instead of writing that code? :)

The output from the public static print method() can look like:
gridx: RELATIVE
gridy: RELATIVE
gridwidth: REMAINDER
gridheight: 1
weightx: 0.0
weighty: 0.0
anchor: ABOVE_BASELINE - Baseline relative
fill: VERTICAL

Btw, I found a spelling error in the official documentation when writing
that code (that exists in the docs for both java 6 and 7). The word
relvative appears under the description of the anchor field (I've
retained it in my comment of my Anchor enum).

Armed with this helper class I will now try to work GridBagLayout work
as I want it. I have another control I want place in a particular place
apart from the centered JPanel in my OP. I will post back if I can't
make it work.

- F

Be sure to check out my GridBagLayout tester program at;

http://rabbitbrush.frazmtn.com/gridbagtester.html
 
F

Fencer

Be sure to check out my GridBagLayout tester program at;

http://rabbitbrush.frazmtn.com/gridbagtester.html

Thanks for that link, I will be sure to bookmark it! Below is my updated
program: It has a "group panel" in the center. The group panel holds two
buttons on the same line with space around them. At the bottom of
frame's content pane I have label acting as a status bar.

I know the code is overly verbose, it's for my learning purposes. I
can't say I have mastered GridBagLayout at all yet, but I can say I will
be using it from now on as much as I can so I do learn it.

One question about my program code, if I want to make the buttons have
the same width, how should I do that? Basically I want the button with
longest text to have its preferred width then increase the width of any
thinner buttons. In my case the button labeled "Open BioModel" should
have its width increased to match that of the button labeled "Load Saved
Session".

Here's the complete code:

package main;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

public class CenteredGroup {

public CenteredGroup() {
frame = new JFrame("BioModel explorer");

frame.setSize(640, 480);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

contentPane = (JPanel)frame.getContentPane();

contentPane.setLayout(new GridBagLayout());

JPanel groupPanel = new JPanel();

groupPanel.setPreferredSize(new Dimension(480, 100));
groupPanel.setBorder(new TitledBorder("Start a new session by
opening a BioModel or load a previously saved session"));
groupPanel.setLayout(new GridBagLayout());

JButton b1 = new JButton("Open BioModel");
JButton b2 = new JButton("Load Saved Session");

addButtonsToGroupPanel(groupPanel, b1, b2);

addGroupPanel(groupPanel);

statusLabel = new JLabel("My Status Bar");

statusLabel.setBorder(BorderFactory.createLineBorder(Color.BLUE,10));

addStatusLabel(statusLabel);
}

public void show() {
frame.setVisible(true);
}

protected void addGroupPanel(JPanel groupPanel) {
GridBagConstraints gbc = new GridBagConstraints();

gbc.gridx = 1;
gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.NONE;

contentPane.add(groupPanel, gbc);
}

protected void addStatusLabel(JLabel statusLabel) {
GridBagConstraints gbc = new GridBagConstraints();

gbc.gridx = 0;
gbc.gridy = 2;
gbc.gridwidth = 3;
gbc.gridheight = 1;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.anchor = GridBagConstraints.LAST_LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;

frame.getContentPane().add(statusLabel, gbc);
}

protected void addButtonsToGroupPanel(JPanel groupPanel, JButton b1,
JButton b2) {
GridBagConstraints gbc = new GridBagConstraints();

gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 0.5;
gbc.weighty = 0;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.NONE;

groupPanel.add(b1, gbc);

gbc.gridx = 1;

groupPanel.add(b2, gbc);
}

public static void main(String[] args) {
CenteredGroup inst = new CenteredGroup();

inst.show();
}

private JFrame frame = null;

private JPanel contentPane = null;

private JLabel statusLabel = null;
}

- F
 
M

markspace

Fencer said:
One question about my program code, if I want to make the buttons have
the same width, how should I do that?


I just click the "same size" button. (In the code below, I think that's
implemented with the jPanel1Layout.linkSize(...) call.)

Here's some code that took me less than five minutes to lay out in a GUI
editor. It's not exactly the same as your code, but I did it by eye
rather than carefully copying what you did. And the buttons are
constrained to be the same size.

/*
* BioModelExplorer.java
*
* Created on Feb 16, 2010, 12:55:06 PM
*/

package test;


public class BioModelExplorer extends javax.swing.JFrame {

/** Creates new form BioModelExplorer */
public BioModelExplorer() {
initComponents();
}

/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

jPanel1 = new javax.swing.JPanel();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jPanel2 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();


setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);


jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Start a
new session"));

jButton1.setText("Open BioModel");

jButton2.setText("Load a Saved Session");

javax.swing.GroupLayout jPanel1Layout = new
javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(

jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(28, 28, 28)
.addComponent(jButton1,
javax.swing.GroupLayout.PREFERRED_SIZE, 103,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(76, 76, 76)
.addComponent(jButton2,
javax.swing.GroupLayout.PREFERRED_SIZE, 137,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(45, Short.MAX_VALUE))
);

jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL,
new java.awt.Component[] {jButton1, jButton2});

jPanel1Layout.setVerticalGroup(

jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(36, 36, 36)

..addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton2)
.addComponent(jButton1))
.addContainerGap(41, Short.MAX_VALUE))
);


jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new
java.awt.Color(51, 51, 255), 10));

jLabel1.setText("Status bar...");

javax.swing.GroupLayout jPanel2Layout = new
javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(

jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addContainerGap(399, Short.MAX_VALUE))
);
jPanel2Layout.setVerticalGroup(

jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
jPanel2Layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE)
.addComponent(jLabel1)
.addContainerGap())
);

javax.swing.GroupLayout layout = new
javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()

..addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

..addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addComponent(jPanel2,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())

..addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addComponent(jPanel1,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(44, 44, 44))))
);
layout.setVerticalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addGap(156, 156, 156)
.addComponent(jPanel1,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)

..addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
118, Short.MAX_VALUE)
.addComponent(jPanel2,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);

pack();
}// </editor-fold>

/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new BioModelExplorer().setVisible(true);
}
});
}

// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
// End of variables declaration

}
 
K

Knute Johnson

Thanks for that link, I will be sure to bookmark it! Below is my updated
program: It has a "group panel" in the center. The group panel holds two
buttons on the same line with space around them. At the bottom of
frame's content pane I have label acting as a status bar.

I know the code is overly verbose, it's for my learning purposes. I
can't say I have mastered GridBagLayout at all yet, but I can say I will
be using it from now on as much as I can so I do learn it.

One question about my program code, if I want to make the buttons have
the same width, how should I do that? Basically I want the button with
longest text to have its preferred width then increase the width of any
thinner buttons. In my case the button labeled "Open BioModel" should
have its width increased to match that of the button labeled "Load Saved
Session".

GBL can make them the same width really easily if they are vertically
aligned with the fill element. Horizontally like that is a little more
difficult. You have to resort to tricks. Once you know the size of the
bigger one which you only will after the container is sized then you can
set the smaller one to the same size.

I have recreated your code to give you a simpler way of presenting your
application. One note, only one GridBagConstraints object is usually
necessary. Just adjust the fields and add your component with a
reference to the GBC and change the fields as necessary. You will see
in the example below I use only one but for two different components.

Also, you don't need to get at the ContentPane any more before adding
components to a JFrame. The add method has been overridden to add the
components to the ContentPane of the JFrame.

Back to the trick. Use a ComponentListener to check for a component
resized event. A resize event is triggered when the component is first
sized for display. Then set the preferred size of the other component
and call revalidate() which causes the component to be redrawn and
triggers another resized event.

The only other thing I might mention is that you have too many fixed
sizes for panels and frames. Usually one creates the content and then
calls pack() on the frame to size your application. That's not always
possible however but given wide range of display resolutions these days,
it is sometimes better to have fixed sizes. My example below uses your
sizes however.

Oh, and one other thing. Swing (JFrame, JWindow etc) GUI creation must
occur on the Event Dispatch Thread (search Google for EDT). That is
accomplished many ways but the simplest is to use the
EventQueue.invokeLater() method to wrap all GUI creation code.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class CG extends JFrame {
public CG() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();

JPanel p = new JPanel(new GridBagLayout());
p.setPreferredSize(new Dimension(480,100));
p.setBorder(new TitledBorder("Panel Border"));

c.gridx = 0;
c.weightx = 1.0;
final JButton b1 = new JButton("Press Me");
p.add(b1,c);

c.gridx = 1;
final JButton b2 = new JButton("Please Don't Press Me");
p.add(b2,c);

b1.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent ce) {
b1.setPreferredSize(b2.getPreferredSize());
b1.revalidate();
System.out.println(b1.getSize());
System.out.println(b2.getSize());
}
});

c.gridx = c.gridy = 0;
c.weighty = 1.0; // c.weightx is still 1.0
c.anchor = GridBagConstraints.CENTER;
add(p,c);

c.gridy = 1;
c.weighty = 0.1; // the panel above gets most of the weighty
c.fill = GridBagConstraints.HORIZONTAL; // c.weightx is still 1.0
c.anchor = GridBagConstraints.SOUTH;
JLabel l = new JLabel(
"Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
Blah");
l.setBorder(BorderFactory.createLineBorder(Color.BLUE,10));
add(l,c);
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
CG cg = new CG();
cg.setSize(640,480);
cg.setLocationRelativeTo(null);
cg.setVisible(true);
}
});
}
}
 
F

Fencer

GBL can make them the same width really easily if they are vertically
aligned with the fill element. Horizontally like that is a little more
difficult. You have to resort to tricks. Once you know the size of the
bigger one which you only will after the container is sized then you can
set the smaller one to the same size.

Ok, I think I will wait a while doing this then, it was only a detail
anyway.
I have recreated your code to give you a simpler way of presenting your
application. One note, only one GridBagConstraints object is usually
necessary. Just adjust the fields and add your component with a
reference to the GBC and change the fields as necessary. You will see in
the example below I use only one but for two different components.

Yes, I know I was being overly verbose in my code. :)
Also, you don't need to get at the ContentPane any more before adding
components to a JFrame. The add method has been overridden to add the
components to the ContentPane of the JFrame.

Ah, thanks for the tip!
Back to the trick. Use a ComponentListener to check for a component
resized event. A resize event is triggered when the component is first
sized for display. Then set the preferred size of the other component
and call revalidate() which causes the component to be redrawn and
triggers another resized event.

The only other thing I might mention is that you have too many fixed
sizes for panels and frames. Usually one creates the content and then
calls pack() on the frame to size your application. That's not always
possible however but given wide range of display resolutions these days,
it is sometimes better to have fixed sizes. My example below uses your
sizes however.

I don't really know how to deal with the problem. I had, for example, to
adjust the width of the "group panel" before the entire titles border
was visible.
Oh, and one other thing. Swing (JFrame, JWindow etc) GUI creation must
occur on the Event Dispatch Thread (search Google for EDT). That is
accomplished many ways but the simplest is to use the
EventQueue.invokeLater() method to wrap all GUI creation code.

Thank you, I've changed that, but I don't want to inherit from JFrame.
[snip code]

- F
 
L

Lew

Thank you, I've changed that, but I don't want to inherit from JFrame.
[snip code]

Sorry?

You used 'JFrame' in your original post. The question of whether to extend
'JFrame' (I'm with you in preferring to compose it) is orthogonal to the need
to put all GUI work on the EDT.

Did I misconstrue something? Perhaps your sentence means that you put the GUI
creation on the EDT, but you don't want to inherit from 'JFrame'. I just
don't get how the inheritance comment connects to what Knute wrote about the EDT.
 
F

Fencer

Thank you, I've changed that, but I don't want to inherit from JFrame.
[snip code]

Sorry?

You used 'JFrame' in your original post. The question of whether to
extend 'JFrame' (I'm with you in preferring to compose it) is orthogonal
to the need to put all GUI work on the EDT.

Did I misconstrue something? Perhaps your sentence means that you put
the GUI creation on the EDT, but you don't want to inherit from
'JFrame'. I just don't get how the inheritance comment connects to what
Knute wrote about the EDT.

Ok, extend, not inherit, I prefer composition, yes. That comment is not
related to the EDT and reading what I wrote again I can see that I
should have separated those two statements more clearly. But I must say
there is something in your tone I don't like but perhaps (hopefully)
that too is a misunderstanding.

- F
 
L

Lew

Knute said:
Oh, and one other thing. Swing (JFrame, JWindow etc) GUI creation must
occur on the Event Dispatch Thread (search Google for EDT). That is
accomplished many ways but the simplest is to use the
EventQueue.invokeLater() method to wrap all GUI creation code.
Thank you, I've changed that, but I don't want to inherit from JFrame.
[snip code]
Sorry?

You used 'JFrame' in your original post. The question of whether to
extend 'JFrame' (I'm with you in preferring to compose it) is orthogonal
to the need to put all GUI work on the EDT.

Did I misconstrue something? Perhaps your sentence means that you put
the GUI creation on the EDT, but you don't want to inherit from
'JFrame'. I just don't get how the inheritance comment connects to what
Knute wrote about the EDT.
Ok, extend, not inherit, I prefer composition, yes. That comment is not
related to the EDT and reading what I wrote again I can see that I
should have separated those two statements more clearly. But I must say
there is something in your tone I don't like but perhaps (hopefully)
that too is a misunderstanding.

That "tone" to which you refer was confusion. Frankly, I don't see what in
what I said could have offended you. I was simply asking for clarification of
a sentence that I didn't understand.

Have a nice day.
 
K

Knute Johnson

I don't really know how to deal with the problem. I had, for example, to
adjust the width of the "group panel" before the entire titles border
was visible.

TitledBorder has a method to provide the minimum size necessary to
display the complete text, TitledBorder.getMinimumSize(). It appears to
have a bug though and not calculate the height correctly. But even that
can be gotten around by using the original preferred height with the
width returned from the getMinimumSize() method.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class CG extends JFrame {
public CG() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridBagLayout());

GridBagConstraints c = new GridBagConstraints();

JPanel p = new JPanel(new GridBagLayout());
TitledBorder tb = new TitledBorder(
"Start an new session by opening a BioModel or laod a" +
" previously saved session");
p.setBorder(tb);

c.gridx = 0;
c.weightx = 1.0;
final JButton b1 = new JButton("Press Me");
p.add(b1,c);

c.gridx = 1;
final JButton b2 = new JButton("Please Don't Press Me");
p.add(b2,c);

b1.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent ce) {
b1.setPreferredSize(b2.getPreferredSize());
b1.revalidate();
System.out.println(b1.getSize());
System.out.println(b2.getSize());
}
});

c.gridx = c.gridy = 0;
c.weighty = 1.0; // c.weightx is still 1.0
c.anchor = GridBagConstraints.CENTER;
add(p,c);

// this needs to be after all the components are added to JPanel p
p.setPreferredSize(new Dimension(
tb.getMinimumSize(p).width,p.getPreferredSize().height));

c.gridy = 1;
c.weighty = 0.1; // the panel above gets most of the weighty
c.fill = GridBagConstraints.HORIZONTAL; // c.weightx is still 1.0
c.anchor = GridBagConstraints.SOUTH;
JLabel l = new JLabel("Blah Blah Blah Blah Blah Blah");
l.setBorder(BorderFactory.createLineBorder(Color.BLUE,10));
add(l,c);
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
CG cg = new CG();
cg.setSize(640,480);
cg.setLocationRelativeTo(null);
cg.setVisible(true);
}
});
}
}
 
A

Andrew Thompson

...One question about my program code, ..

Famous last words. ;)
...if I want to make the buttons have
the same width, how should I do that? ...

Put the components in a GridLayout in a JPanel.
Add that JPanel to the GridBagLayout.

And as an aside: What is it with GBL experts where
they feel they have to prove that 'anything is possible
with GBL'? If there is a layout better suited to
part of a GUI, use it!
 
R

RedGrittyBrick

I just click the "same size" button. (In the code below, I think that's
implemented with the jPanel1Layout.linkSize(...) call.)

/**
* Make some buttons all be the same width:
*
* <pre>
* Utils.equalizeButtonWidths(new JButton[] { addButton,
* editButton, removeButton,
* printButton, viewButton });
* </pre>
*
* @param buttons
* an array of JButtons
*/
public static void equalizeButtonWidths(JButton[] buttons) {
int maxWidth = 0;
int maxHeight = 0;
for (JButton b : buttons) {
Dimension size = b.getPreferredSize();
int w = size.width;
int h = size.height;
if (w > maxWidth)
maxWidth = w;
if (h > maxHeight)
maxHeight = h;
}
Dimension buttonSize = new Dimension(maxWidth, maxHeight);
for (JButton b : buttons) {
b.setMinimumSize(buttonSize);
b.setPreferredSize(buttonSize);
b.setMaximumSize(buttonSize);
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top