Aligning components in Box - java

edit: if you downvote this question, you may leave a comment to explain why, that will be more constructive.
I obtain this unexpected result...
... using this code:
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TestAlignment extends JFrame {
// Constructor
public TestAlignment() {
super("Test Alignment");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Components to show
JLabel leftLabel = new JLabel("Left");
JButton centerButton = new JButton("Middle");
JLabel rightLabel = new JLabel("Right");
// Add all to box
Box box = Box.createVerticalBox();
box.add(leftLabel);
box.add(centerButton);
box.add(rightLabel);
box.add(Box.createHorizontalStrut(180));
// Align content in box
leftLabel.setAlignmentX(LEFT_ALIGNMENT);
centerButton.setAlignmentX(CENTER_ALIGNMENT);
rightLabel.setAlignmentX(RIGHT_ALIGNMENT);
// Add box to frame, and show frame
box.setOpaque(true);
setContentPane(box);
setVisible(true);
}
// Main
public static void main(String[] args) {
// Create frame in EDT
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() { new TestAlignment(); }
});
}
}
I understand now this works as expected for JComponent.setAlignmentX(): this method tells which sides of the components must be aligned (top label leftmost side aligned with button center and bottom label rightmost side).
I would like to understand how to have each label aligned as expected intuitively (left label on the left, right label on the right), labels touching the vertical edges of the Box?
(I know how to do with putting each label in a Box embedded, and using Box.createHorizontalGlue() to force it to the left or the right side, but seems to me too much for the simple purpose of alignment. I'm looking for something more simple)

Don't think you can do this with a BoxLayout. Your example does show the intuitive code, which doesn't work as you would hope.
I would suggest you probably need to use a GridBagLayout. I think it supports the setAlignmentX(...) method the way you want to use it.
If not, then can use the Relative Layout. It is simple to use, like the BoxLayout and does support the alignment you want when you use:
setAlignment( RelativeLayout.COMPONENT );

You can use BoxLyout:
// Components to show
// Left
JLabel leftLabel = new JLabel("Left");
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.X_AXIS));
leftPanel.add(leftLabel);
leftPanel.add(Box.createHorizontalGlue());
// Center
JButton centerButton = new JButton("Middle");
// Right
JLabel rightLabel = new JLabel("Right");
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.X_AXIS));
rightPanel.add(Box.createHorizontalGlue());
rightPanel.add(rightLabel);
// Add all to box
Box box = Box.createVerticalBox();
box.add(leftPanel);
box.add(centerButton);
box.add(rightPanel);
box.add(Box.createHorizontalStrut(180));
// Align content in box
// leftLabel.setAlignmentX(LEFT_ALIGNMENT);
centerButton.setAlignmentX(CENTER_ALIGNMENT);
// rightLabel.setAlignmentX(RIGHT_ALIGNMENT);

Related

How do I add a scrollbar to a JFrame with setLayout(null)?

I have some components which I need to use setBounds() on, hence the reason why I'm using the setLayout(null).
But some of my components are out the window(below the Y-axis). I was wondering if there is a way to add a scrollbar to navigate down the window so as to see all the remaining components. A screenshot of my window is below.
Output of my window image:
That GUI would be simple to produce using layouts. Put the component displaying the list (which looks well suited to being a JTable, given the two pieces of data per row / line) into a JScrollPane. Put the scroll pane into the CENTER of a BorderLayout. Put the red label into the PAGE_START of the border layout. Then .. oh wait, the job is done!
This is what it might look like (using a JTextArea instead of a table).
can u please post a copy of this code.
Try implementing it based on the instructions above. If there is a problem, post a minimal reproducible example of your attempt.
Since you are refering to the items in the scrolling area as components, and not as texts in a JTextArea, please have a look at the below.
import java.awt.*;
import javax.swing.*;
import java.util.Random;
public class Mainframe {
private JFrame f;
Box box;
JScrollPane scrollPane;
Random rand = new Random();
public static void main(String[] args) {
new Mainframe().go();
}
private void go() {
box = new Box(BoxLayout.Y_AXIS);
JLabel label = new JLabel("Possible Paths and Total Distances");
label.setForeground(Color.RED);
for (int i = 0; i < 200; i++) {
box.add(Box.createRigidArea(new Dimension(0, 2)));// creates space between the components
box.add(new JLabel(i + " : " + rand.nextInt(10000)));
}
scrollPane = new JScrollPane(box);
Dimension dim = new Dimension(box.getComponent(0).getPreferredSize());
scrollPane.getVerticalScrollBar().setUnitIncrement(dim.height * 2); // adjusts scrolling speed
//scrollPane.getViewport().setBackground(Color.WHITE);
f = new JFrame();
f.getContentPane().add(label, BorderLayout.NORTH);
f.getContentPane().add(scrollPane, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(640, 480);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

Layout - Relative to screensize

So I am a computer science student and I've finished my first year. I wanted to create a simple program and I realized that I am so tired of using no layout;
this.setLayout(null);
It is so tiresome to add bounds to every single component. Well, I have been using JPanel components and GridLayout a lot, which have made my work a bit easier. But I am tired of it.
I care very much about the look of the GUI I make and use almost half the time programming to make the GUI look good before I start adding the functionality of the code. By not using a layout and adding bounds I am forced to setResizable(false) because it looks bad if I change the size of the JFrame.
I've been searching a bit, and I know of BorderLayout, and FlowLayout, but I don't like them. Is there any Layout that keeps the relative size of the components with respect to the size of the window?
For example I want to make a simple program that looks like this: (Quick sketch in Photoshop)
I can easily make this with 3 panels, but as I said, if I change the size of the frame everything stays in place instead of being relative to the window-size.
Can you guys help me?
This design looks for me to fit the BorderLayout, where in the NORTH you have the values that changes the CENTER you have the main part, and the SOUTH you have the buttons.
Link to the Oracle Border Layout
You can apply this BorderLayout to the JFrame, then create 3 JPanels for each of the NORTH,CENTER and SOUTH sections. If you want to use responsive design for the components and panels, take a look at GridBagLayout which is much more flexible than the GridLayout
Layout management is a very complex problem, I don't think people really appreciate just how complex it really is.
No one layout is ever going to achieve everything your want, in most cases, you will need to resort to two or more layouts, especially as your requirements become more complex.
For example, the following is simply a BorderLayout at the base and the buttons on a JPanel using a FlowLayout
Which is achieved by using
JList listOfThings = new JList(...);
JTextField tf = new JTextField();
JButton add = new JButton("Add");
JButton delete = new JButton("Delete");
JButton go = new JButton("Go...");
JPanel buttons = new JPanel();
buttons.add(add);
buttons.add(delete);
buttons.add(go);
add(new BorderLayout());
add(tf, BorderLayout.NORTH);
add(new JScrollPane(listOfThings));
add(buttons, BorderLayout.SOUTH);
For more complex layouts, I would consider using something like GridBagLayout. You may also want to consider MigLayout as an alternative
Take a look at Laying Out Components Within a Container for more details about using layout managers
I'd like to use the combination of BorderLayout and BoxLayout. BorderLayout let me put the component based on their relative location's relation and BoxLayout let me manage the subtle distance ( create some white space). You can use component.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); to achieve this goal too.
Here is a demo and hope it can help you.
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class LayoutTest{
private JTextField jTextField;
public void createUI(){
JFrame frame = new JFrame("Layout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
JPanel mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.add(new TextFieldPanel());
mainPanel.add(Box.createVerticalStrut(8));
mainPanel.add(new ListPanel());
mainPanel.add(Box.createVerticalStrut(8));
mainPanel.add(new ButtonPanel());
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
LayoutTest layoutTest = new LayoutTest();
layoutTest.createUI();
}
#SuppressWarnings("serial")
class TextFieldPanel extends JPanel{
public TextFieldPanel(){
setLayout(new BorderLayout());
jTextField = new JTextField();
jTextField.setEditable(false);
add(jTextField,BorderLayout.CENTER);
}
}
#SuppressWarnings("serial")
class ListPanel extends JPanel implements ListSelectionListener{
private JList<String> list;
public ListPanel(){
setLayout(new BorderLayout());
String stringArr[] = new String[30];
for (int i = 0; i < 30; i++) {
stringArr[i] = "JList :This line is item" + i;
}
list = new JList<String>(stringArr);
JScrollPane scrollPane = new JScrollPane(list);
add(scrollPane,BorderLayout.CENTER);
setBackground(new Color(211,211,211));
list.addListSelectionListener(this);
}
#Override
public void valueChanged(ListSelectionEvent e) {
// TODO Auto-generated method stub
jTextField.setText(list.getSelectedValue());
}
}
#SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
setLayout(new BorderLayout());
add(button1,BorderLayout.WEST);
add(button2,BorderLayout.CENTER);
add(button3,BorderLayout.EAST);
}
}
}
Here is the effect:
You can use BoxLayout for ButtonPanel if you don't want to let the button's size change.
#SuppressWarnings("serial")
class ButtonPanel extends JPanel{
public ButtonPanel(){
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(button1);
add(Box.createHorizontalStrut(8));
add(button2);
add(Box.createHorizontalStrut(8));
add(button3);
}
}
And the effect is like this:
For more infomation about using BoxLayout to generate whitespace, you can refer to https://stackoverflow.com/a/22525005/3378204
Try GridBagLayout.
Your sketch is actually quite close to the one of the examples in the official tutorial.
HVLayout keeps the relative size of the components with respect to the size of the window, that is, if you configure components to have a relative size (e.g. buttons usually do not grow or shrink - they stick to their preferred size). This SO question was one of the motivations for me to push HVLayout to a release and a screenshot is included (showing big window size, smalll size and preferred "default" size):
Source code for the window is in RelativeToWindowSize.java
A number of helper-classes from HVLayout are used to build the window, so I don't think it will be of much use here, but to get an impression, the "build window" part shown below:
public RelativeToWindowSize build() {
CSize cs = new CSize();
CForm form = new CForm(new VBox(new Insets(2, 4, 2, 4)), cs);
addTitledBorder(form.get(), "Vertical box", Color.BLACK);
form.add(new JScrollPane(
tfield = new JTextArea("Value that changes with value choosen from list.\nhttp://stackoverflow.com/questions/24462297/layout-relative-to-screensize/")
)).csize().setAreaSize(1.0f, 2.5f).fixedMinHeight().setMaxHeight(4.0f);
// tfield shows mono-spaced font by default.
tfield.setFont(SwingUtils.getUIFont());
form.add(new JScrollPane(vlist = new JList<String>(getListValues())))
.csize().setAreaSize(1.0f, 5.0f);
form.addChild(new HBox());
addTitledBorder(form.get(), "Horizontal box", Color.RED);
form.addChild(new HBox(SwingConstants.CENTER));
addTitledBorder(form.get(), "Centered box.", Color.BLUE);
form.add(createButton(cs, "Add"));
form.add(createButton(cs, "Modify"));
form.up();
form.addChild(new HBox(SwingConstants.TRAILING));
addTitledBorder(form.get(), "Trailing box", Color.GREEN);
form.add(createButton(cs, "Delete"));
setContentPane(form.getRoot());
pack();
setLocationByPlatform(true);
//applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
vlist.addListSelectionListener(this);
log.debug(getClass().getName() + " build.");
return this;
}
private Component createButton(CSize cs, String text) {
// For purpose of demo, let button shrink in width.
return cs.set(new TButton(text)).setFixed().shrinkWidth(0.33f).get();
}

How do I customize a JSplitPane divider and maintain one-touch arrow functionality?

So, my problem boils down to this... The default dividers are kind of ugly, plus I would like to add a label to it (in the I-want-text-on-it sense, not in the "adding a JLabel to its layout" sense). I see that you can change the border on the split pane divider, but when I do that, it removes the one-touch arrows, which I want to keep around.
Any thoughts on how I can have both?
Here's a SSCCE that demonstrates both the default behavior and what happens when I change the divider border:
import javax.swing.*;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SplitPaneFun {
public static void main(String[] args) {
//Here I'm messing around with the divider look. This seems to remove the one-touch arrows. These blocked-out lines illustrate
// what I'm doing to modify the divider's border. Does this look right?:
//------------------------------------------------------------------------------------------------
JSplitPane withCustomDivider = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JPanel(), new JPanel());
BasicSplitPaneDivider divider = ( (BasicSplitPaneUI) withCustomDivider.getUI()).getDivider();
withCustomDivider.setOneTouchExpandable(true);
divider.setDividerSize(15);
divider.setBorder(BorderFactory.createTitledBorder(divider.getBorder(), "Custom border title -- gets rid of the one-touch arrows!"));
//------------------------------------------------------------------------------------------------
//build a different splitpane with the default look and behavior just for comparison
JSplitPane withDefaultDivider = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JPanel(), new JPanel());
withDefaultDivider.setOneTouchExpandable(true);
//slap it all together and show it...
CardLayout splitsLayout = new CardLayout();
final JPanel splits = new JPanel(splitsLayout);
splits.add(withCustomDivider, "custom");
splits.add(withDefaultDivider,"default");
JButton toggle = new JButton( "click to see the other split pane");
toggle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
((CardLayout)splits.getLayout()).next(splits);
}
});
JFrame frame = new JFrame("Split Pane Divider Comparison");
frame.setLayout(new BorderLayout());
frame.add(splits, BorderLayout.CENTER);
frame.add(toggle, BorderLayout.PAGE_END);
frame.setSize(600,500);
frame.setVisible(true);
}
}
I see that you can change the border on the split pane divider, but when I do that, it removes the one-touch arrows, which I want to keep around.
all these methods is possible to override the events from Mouse(Xxx)Listener, PropertyChangeListener and ButtonModel, nothing better around as Substance SubstanceSplitPaneDivider
part of Custom Look and Feels override these methods too

Swing BoxLayout problem with JComboBox without using setXXXSize

here's an SSCCE:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BoxLayoutTest extends JFrame {
public BoxLayoutTest(){
JPanel main = new JPanel();
main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
main.setBackground(Color.red);
this.add(main);
JPanel northPanel = new JPanel();
JPanel middle = new JPanel();
middle.setLayout(new BoxLayout(middle, BoxLayout.X_AXIS));
middle.add(new JButton("FOO"));
middle.add(Box.createHorizontalGlue());
JPanel aPanel = new JPanel();
aPanel.setBackground(Color.black);
JComboBox b = new JComboBox();
//b.setPreferredSize(new Dimension(100,16)); //uncomment this to see the layout I would like to achieve
//b.setMaximumSize(new Dimension(100,16));
//middle.add(b); //uncomment this line
middle.setBackground(Color.green);
northPanel.setBackground(Color.blue);
main.add(northPanel);
main.add(middle);
main.add(Box.createVerticalGlue());
this.setSize(800,600);
this.setResizable(true);
this.setVisible(true);
}
public static void main(String[] args) {
new BoxLayoutTest();
}
}
I'm trying to refactor some classes I wrote some time ago, when I didn't know that using setXXXSize methods on components is wrong.
Using a resizable frame ,the result I want to achieve is the following:
The northPanel should stay on top and change it's size accordingly to the frame size modifications (seems to work fine)
The green panel where I put the JButton should keep the maximum dimension of the JButton and stay just below the blue panel above (this works fine if I only put JButtons inside that panel).
The problem arise if I put a JComboBox inside the green panel (try to uncomment the line in the SSCCE). I guess JComboBox hasn't a maximum size specified, so it stretches with the frame. In the previous wrong version of my code I was using setxxxSize methods on the JComboBox to limit it's dimension(try to uncomment the line on setXXXSize methods to see it).
My question are:
Is it possible to achieve the same result using BoxLayout without invoking setXXXSize() methods?
If yes, how?
Is there any other LayoutManager that can I use to get that effect?
Please put me in the right direction
JComboBox is misbehaving (the same as JTextField) in reporting an unbounded max height: should never show more than a single line. Remedy is the same: subclass and return a reasonable height
JComboBox b = new JComboBox() {
/**
* #inherited <p>
*/
#Override
public Dimension getMaximumSize() {
Dimension max = super.getMaximumSize();
max.height = getPreferredSize().height;
return max;
}
};
just for fun, here's a snippet using MigLayout (which is my personal favorite currently :-)
// two panels as placeholders
JPanel northPanel = new JPanel();
northPanel.setBackground(Color.YELLOW);
JPanel southPanel = new JPanel();
southPanel.setBackground(Color.YELLOW);
// layout with two content columns
LC layoutContraints = new LC().wrapAfter(2)
.debug(1000);
AC columnContraints = new AC()
// first column pref, followed by greedy gap
.size("pref").gap("push")
// second
.size("pref");
// three rows, top/bottom growing, middle pref
AC rowContraints = new AC()
.grow().gap().size("pref").gap().grow();
MigLayout layout = new MigLayout(layoutContraints, columnContraints,
rowContraints);
JPanel main = new JPanel(layout);
main.setBackground(Color.WHITE);
// add top spanning columns and growing
main.add(northPanel, "spanx, grow");
main.add(new JButton("FOO"));
// well-behaved combo: max height == pref height
JComboBox combo = new JComboBox() {
#Override
public Dimension getMaximumSize() {
Dimension max = super.getMaximumSize();
max.height = getPreferredSize().height;
return max;
}
};
// set a prototype to keep it from constantly adjusting
combo.setPrototypeDisplayValue("somethingaslongasIwant");
main.add(combo);
// add top spanning columns and growing
main.add(southPanel, "spanx, grow");
I have always seen using the layout managers in the jdk are not easy. They are either too simple and inflexible or the gridbaglayout is just too much trouble. Instead I started using the jgoodies form layout and never looked back since.. Have a look at it. Its very simple and easy to use. Here's a link:
http://www.jgoodies.com/freeware/forms/
Make sure you go through the white paper.
And now, we also have google providing us a WYSISWG editor for the formlayout as a plugin for eclipse. This just makes life a lot lot easier.
http://code.google.com/javadevtools/wbpro/palettes/swing_palette.html

Positioning in java swing

I have some troubles with positioning my label/password field.
With this code they both get positioned in the center next to each other, while I actually want them in the middle of my panel on top of each other.
Does anyone know how I should do that?
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
public class Paneel_Pincode extends JPanel {
Paneel_Pincode() {
setLayout(new FlowLayout());
JPasswordField pincode = new JPasswordField(15);
pincode.setLocation(500, 500);
JLabel pinInvoer = new JLabel();
ImageIcon pin1 = new ImageIcon("images/voerPincodeIn.jpg");
pinInvoer.setIcon(pin1);
pinInvoer.setLocation(500,700);
add(pincode);
add(pinInvoer);
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1000,1000);
f.setLocationRelativeTo(null);
f.add(new Paneel_Pincode());
f.setVisible(true);
}
}
To get the hang of layouts, I'd recommend reading my article on them (http://java.sun.com/developer/onlineTraining/GUI/AWTLayoutMgr/). It's old, but the concepts and how FlowLayout works are detailed.
What do you mean by "on top of each other"?
If you mean like
Password
<field>
EDIT: I REMEMBERED AN EASIER WAY TO DO THIS (completely in the JDK/JRE)...
(This is similar to what I'm doing with the BoxBeans below, but you don't need the BoxBeans. I created BoxBeans to be able to use BoxLayout in a UI builder a long time ago...)
JLabel label = new JLabel("Password") {
#Override public Dimension getMaximumSize() {
return super.getPreferredSize();
}
};
JPasswordField field = new JPasswordField() {
#Override public Dimension getMaximumSize() {
return super.getPreferredSize();
}
};
field.setColumns(10);
Box verticalBox = Box.createVerticalBox();
verticalBox.add(Box.createVerticalGlue());
verticalBox.add(label);
verticalBox.add(field);
verticalBox.add(Box.createVerticalGlue());
//
Box horizontalBox = Box.createHorizontalBox();
horizontalBox.add(Box.createHorizontalGlue());
horizontalBox.add(verticalBox);
horizontalBox.add(Box.createHorizontalGlue());
add(horizontalBox);
Previous answer for reference...
I DO NOT RECOMMEND THE FOLLOWING BUT IT MAY HELP OTHER READERS WITH IDEAS
You can do something like
setLayout(FlowLayout());
JPanel group = new JPanel(new BorderLayout());
group.add(new JLabel("Password"), BorderLayout.NORTH);
group.add(passwordField, BorderLayout.SOUTH);
add(group);
This will create a little panel in the top-center of the overall UI that contains the Password and field.
Note that the nested BorderLayout ensures that the label and field each get their preferred size. You'll need to call setColumns on the field to the number of chars you'd like displayed.
If you want to center the label/field vertically as well, you could do the following
setLayout(new GridBagLayout());
//
add(new JLabel("Password"),
new GridBagConstraints(0,0,1,1,1,1,
GridBagConstraints.SOUTH,GridBagConstraints.NONE,
new Insets(3,3,3,3), 0,0));
field.setColumns(10);
add(field, new GridBagConstraints(0,1,1,1,1,1,
GridBagConstraints.NORTH,GridBagConstraints.NONE,
new Insets(3,3,3,3), 0,0));
I hate using GridBagLayout in general, so I'll add a version using BoxLayout (but it's a bit trickier due to the preferred size settings)
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
//
JPanel stuffH = new JPanel();
f.add(stuffH, BorderLayout.CENTER);
stuffH.setLayout(new BoxLayout(stuffH, BoxLayout.X_AXIS));
//
JPanel stuffV = new JPanel();
stuffV.setLayout(new BoxLayout(stuffV, BoxLayout.Y_AXIS));
//
JLabel label = new JLabel("Password");
BoxAdapter labelAdapter = new BoxAdapter();
labelAdapter.add(label);
JPasswordField field = new JPasswordField();
field.setColumns(10);
BoxAdapter fieldAdapter = new BoxAdapter();
fieldAdapter.add(field);
//
stuffV.add(new VerticalGlue()); // for vertical spacing
stuffV.add(labelAdapter);
stuffV.add(fieldAdapter);
stuffV.add(new VerticalGlue()); // for vertical spacing
//
stuffH.add(new HorizontalGlue()); // for horizontal spacing
stuffH.add(stuffV);
stuffH.add(new HorizontalGlue()); // for horizontal spacing
//
f.setVisible(true);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
A few notes on this:
I'm using my BoxBeans helper classes - see http://javadude.com/tools/boxbeans. This page is based on VisualAge for Java, but the jar at the bottom of the page can be used outside VAJ. I just tried it in eclipse, for example.
AFAICS, you cannot set a jframe's layout directly to BoxLayout, so I added an extra panel in between. There's a check in BoxLayout that has trouble with the automatic indirection of the content pane.
I nested the BoxLayouts so there's horizontal centering (the stuffH panel) containing a vertical centering (the stuffV panel). They are centered by surrounding them with "Glue" components, which are simply components that allow themselves to expand.
I had to put the label and field in a BoxAdapter which limits their maximum size to their preferred size. If you don't want to use BoxAdapter, you can acheive the same effect by using the following for the field and label:
JLabel label = new JLabel("Password") {
#Override public Dimension getMaximumSize() {
return super.getPreferredSize();
}
};
JPasswordField field = new JPasswordField() {
#Override public Dimension getMaximumSize() {
return super.getPreferredSize();
}
};
Hope this proves helpful to you and anyone else!
-- Scott
I would recommend the JGoodies FormLayout. Once you learn it, it's quite powerful and easy to do by hand coding.

Categories