I have a simple grid bag layout and when I only use text fields, it works correctly. When I put a JSpinner in, the whole layout gets completely messed up. By this I mean two of my three columns completely disappear, the the second column, the only column that appears, consumes the entire width of the window no matter how the window is sized. The complete code is below.
The problem seems to have something to do with spinners specifically, if I use other kinds of JComponents like JLabel the problem does not manifest itself. What did I do wrong that caused the JSpinner to completely destroy the layout?
package product_data.ui;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
public class StrippedProductEditor extends JFrame {
/**
*
*/
private static final long serialVersionUID = 5429511033322948114L;
private JLabel lblManufacturer;
private JLabel lblSku;
private JTextField mfrText;
private JTextField skuText;
private JTextArea extraText;
private JLabel lblListPrice;
private JSpinner spinner;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new StrippedProductEditor();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public StrippedProductEditor() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[] { 0, 0, 0 };
gridBagLayout.rowHeights = new int[] { 0, 0, 0, };
gridBagLayout.columnWeights = new double[] { 0.0, 1.0, 1.0 };
gridBagLayout.rowWeights = new double[] { 0.0, 0.0, 0.0};
getContentPane().setLayout(gridBagLayout);
lblManufacturer = new JLabel("Manufacturer");
GridBagConstraints gbc_lblManufacturer = new GridBagConstraints();
gbc_lblManufacturer.insets = new Insets(0, 0, 5, 5);
gbc_lblManufacturer.gridx = 0;
gbc_lblManufacturer.gridy = 0;
getContentPane().add(lblManufacturer, gbc_lblManufacturer);
mfrText = new JTextField();
GridBagConstraints gbc_lblMfrText = new GridBagConstraints();
gbc_lblMfrText.insets = new Insets(0, 0, 5, 5);
gbc_lblMfrText.fill = GridBagConstraints.HORIZONTAL;
gbc_lblMfrText.gridx = 1;
gbc_lblMfrText.gridy = 0;
getContentPane().add(mfrText, gbc_lblMfrText);
lblSku = new JLabel("SKU");
GridBagConstraints gbc_lblSku = new GridBagConstraints();
gbc_lblSku.insets = new Insets(0, 0, 5, 5);
gbc_lblSku.gridx = 0;
gbc_lblSku.gridy = 1;
getContentPane().add(lblSku, gbc_lblSku);
skuText = new JTextField();
GridBagConstraints gbc_textField_1 = new GridBagConstraints();
gbc_textField_1.insets = new Insets(0, 0, 5, 5);
gbc_textField_1.fill = GridBagConstraints.HORIZONTAL;
gbc_textField_1.gridx = 1;
gbc_textField_1.gridy = 1;
getContentPane().add(skuText, gbc_textField_1);
skuText.setColumns(10);
extraText = new JTextArea();
JScrollPane dictScrollPane = new JScrollPane(extraText);
GridBagConstraints gbc_dict = new GridBagConstraints();
gbc_dict.insets = new Insets(0, 0, 5, 5);
gbc_dict.gridx = 2;
gbc_dict.gridy = 0;
gbc_dict.gridheight = 2;
gbc_dict.fill = GridBagConstraints.BOTH;
getContentPane().add(dictScrollPane, gbc_dict);
lblListPrice = new JLabel("List Price");
GridBagConstraints gbc_lblListPrice = new GridBagConstraints();
gbc_lblListPrice.insets = new Insets(0, 0, 5, 5);
gbc_lblListPrice.gridx = 0;
gbc_lblListPrice.gridy = 2;
getContentPane().add(lblListPrice, gbc_lblListPrice);
double lp = 99.9;
SpinnerNumberModel m = new SpinnerNumberModel(lp, 0.0d,
Double.MAX_VALUE, 0.01d);
spinner = new JSpinner(m);
GridBagConstraints gbc_spinner = new GridBagConstraints();
gbc_spinner.fill = GridBagConstraints.HORIZONTAL;
gbc_spinner.insets = new Insets(0, 0, 5, 5);
gbc_spinner.gridx = 1;
gbc_spinner.gridy = 2;
//commenting out this line will make the layout look
//correct, but then the spinner is missing.
getContentPane().add(spinner, gbc_spinner);
this.pack();
this.setVisible(true);
}
}
So, after digging around the code a bit, I found that the JSpinner.NumberEditor, which is the editor been used to support the SpinnerNumberModel is calculating the fields columns property by using...
try {
String maxString = formatter.valueToString(model.getMinimum());
String minString = formatter.valueToString(model.getMaximum());
ftf.setColumns(Math.max(maxString.length(),
minString.length()));
}
catch (ParseException e) {
// TBD should throw a chained error here
}
Now, as it turns out, maxString equates to 0 (yeah I know), and minString equates to...
179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
Which equals 411 characters...opps...
Now, you could reduce your models maximum value to something more realistic (like a million for example) or you could adjust the spinners size manually using something like...
((JSpinner.NumberEditor) spinner.getEditor()).getTextField().setColumns(10);
Personally, I prefer option one ;)
The problem arises because your components and layout are underconstrained, but the key problem seems to be that the Spinner's preferred size is not playing nicely with the other components. Everything was much nicer after I added
spinner.setPreferredSize(new Dimension(128, 16));
though column 2 still ended up with width 0. You should set a preferred size on the JTextArea as well to sort that out. Alternatively, you could set a preferred size on the whole JFrame.
If you use eclipse, try it swing plugin http://www.eclipse.org/windowbuilder/
It does all the swing gui stuff for you. Personally it helped me a lot.
Related
I am using GridBagLayout to align components. Actually, i have two buttons which i want to align like this:
Desired layout:
But the following code results in the following layout:
Resulted layout:
My code:
iconAdd = new ImageIcon(getClass().getResource("../images/add.png"));
add = new JButton(iconAdd);
add.setPreferredSize(new Dimension(130, 100));
add.setBorder(new LineBorder(Color.decode("#9b9999"), 1, true));
add.setCursor(Cursor.getPredefinedCursor(12));
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 5, 5);
pane.add(add, gbc);
iconSearch = new
ImageIcon(getClass().getResource("../images/search.png"));
search = new JButton(iconSearch);
search.setCursor(Cursor.getPredefinedCursor(12));
search.setPreferredSize(new Dimension(130, 100));
search.setBorder(new LineBorder(Color.decode("#9b9999"), 1, true));
gbc.gridx++;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 5, 5);
pane.add(search, gbc);
Any help would be highly appreciated.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class GridBagLayoutDemo extends JFrame{
GridBagLayoutDemo(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWeights = new double[]{1.0, 1.0, 1.0};
gridBagLayout.columnWidths = new int[]{0,0,300};
getContentPane().setLayout(gridBagLayout);
JButton button1 = new JButton("Long Button");
GridBagConstraints c1 = new GridBagConstraints();
c1.fill = GridBagConstraints.HORIZONTAL;
c1.weightx = 0.0;
c1.gridwidth = 3;
c1.gridx = 0;
c1.gridy = 0;
getContentPane().add(button1, c1);
JButton button2 = new JButton("Button 2");
GridBagConstraints c2 = new GridBagConstraints();
c2.weightx = 0.5;
c2.gridx = 0;
c2.gridy = 1;
getContentPane().add(button2, c2);
JButton button3 = new JButton("Button 3");
GridBagConstraints c3 = new GridBagConstraints();
c3.weightx = 0.5;
c3.gridx = 1;
c3.gridy = 1;
getContentPane().add(button3, c3);
pack();
setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new GridBagLayoutDemo();
}
});
}
}
gbc.weightx = 1;
You are telling the layout to give extra space to each component. So essentially each component becomes half the size of the frame.
You really only want that constraint set for the second button, so it takes up all the remaining space.
Read the section from the Swing tutorial on How to Use GridBagLayout which explains how the weightx/y constraints should be used.
Also, an easier solution would be do just use a FlowLayout. Create a panel with a FlowLayout. Add the buttons to the panel. Then add the panel to the BorderLayout.PAGE_START of the frame.
I am using GridBagLayout to locate components on panel but it is not working like it has to be. Location of components is not affecting by changing x and y values somebody please help explain what mistake i am making here Thanks in advance :)
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class LMS extends JFrame {
JPanel mainPanel;
JLabel RegNum, Name, FatherNam, MotherNam, DateBirth, BloodGrp, Email, Gender, RegDate, Desig, photo;
JTextField RegNuumText, FatherNamText, MotherNamText, EmailText, DesigText;
JList BloodGrpList;
JSpinner DateSpi;
// Constructor
public LMS() {
this.setTitle("Library Managment System");
this.setVisible(true);
this.setSize(700, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
// this.setResizable(false);
mainPanel = new JPanel();
// GridBagLayout bag = new GridBagLayout();
mainPanel.setLayout(new GridBagLayout());
// Creating Labels
RegNum = new JLabel("Registration Number");
Name = new JLabel("Full Name");
FatherNam = new JLabel("Father's Name");
MotherNam = new JLabel("Mother's Name");
DateBirth = new JLabel("Date Of Birth");
BloodGrp = new JLabel("Blood Group");
Email = new JLabel("Email");
Gender = new JLabel("Gender");
RegDate = new JLabel("Registration Date");
Desig = new JLabel("Designation");
photo = new JLabel("Photo");
// creating Text Fields
RegNuumText = new JTextField(30);
FatherNamText = new JTextField();
MotherNamText = new JTextField();
EmailText = new JTextField();
DesigText = new JTextField();
// mainPanel.add(RegNum);
addComp(mainPanel, RegNum, 0, 0, 2, 1, GridBagConstraints.EAST, GridBagConstraints.NONE);
addComp(mainPanel, RegNuumText, 0, 1, 2, 1, GridBagConstraints.WEST, GridBagConstraints.NONE);
this.add(mainPanel);
}
private void addComp(JPanel thePanel, JComponent comp, int xPos,
int yPos, int compWidth, int compHeight, int place, int stretch) {
GridBagConstraints gridConstraints = new GridBagConstraints();
gridConstraints.gridx = xPos;
gridConstraints.gridy = yPos;
gridConstraints.gridwidth = compWidth;
gridConstraints.gridheight = compHeight;
gridConstraints.weightx = 1;
gridConstraints.weighty = 1;
gridConstraints.insets = new Insets(5, 5, 5, 5);
gridConstraints.anchor = place;
gridConstraints.fill = stretch;
thePanel.add(comp, gridConstraints);
}
public static void main(String[] args) {
new LMS();
}
}
GridBagLayout is not the easiest one, you have to play a little with it. Maybe these lines help you to achieve what you wanted. They will put the label in the upper left corner and the Textfield right behind it.
Note, that there are panels defined as place holders - they will fill the empty space.
addComp(mainPanel, RegNum, 0, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE);
addComp(mainPanel, RegNuumText, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE);
addComp(mainPanel, new JPanel(), 2, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL);
addComp(mainPanel, new JPanel(), 0, 2, 1, 1, GridBagConstraints.WEST, GridBagConstraints.VERTICAL);
You also need to change your helper method a little:
gridConstraints.weightx = stretch == GridBagConstraints.NONE || stretch == GridBagConstraints.VERTICAL ? 0 : 1;
gridConstraints.weighty = stretch == GridBagConstraints.NONE || stretch == GridBagConstraints.HORIZONTAL ? 0 : 1;
I think this should do the trick. Maybe you should define two or three helper methods, so you don't need to set all parameters every time. From my experience, very rarely you will need to define the anchor and only some times you might want to stretch components. Most of the time, for me, it is just puting stuff into the right bags (x, y, sometimes: width, height).
Edit: maybe it would help to put setVisible() at the end of the definition, not the beginning.
I'm learning how to use GridBagLayout. I created two buttons in a JFrame. I tried making it that one of them occupies one collumn (the default), and the other two collumns, thus being twice the size of the first one (I know I can acheive this using setPrefferredSize, but my intention is to learn how to use gridwidth and gridheight).
What's the problem? Thanks
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame {
Main(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500,500);
JPanel panel1 = new JPanel(new GridBagLayout());
JButton b1,b2;
b1 = new JButton("button 1");
b2 = new JButton("button 2");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridwidth = 1;
panel1.add(b1);
gbc.gridx = 2;
gbc.gridwidth = 2;
panel1.add(b2);
add(panel1);
setVisible(true);
}
public static void main(String[]args){
Main m = new Main();
}
}
It doesn't matter how many columns the second button's width.
Actually both buttons will be asked for their preferred width and the width will be set to them if it's enough space for them.
If it's less space then min width is used.
If there is extra space it's distributed between controls according to weights proportions.
You can try to set iPadX=100 for the first and iPadx=200 and set proportion iPadX=1 for the first and iPadx=2 for the second.
The problem is that all the columns of a GridBagLayout don't have the same width. The widths are computed based on the preferred size of the components they contain. So, you could use 3, 4 or 100 as the gridwidth for the second button, it wouldn't change anything.
You need to use fillx and weightx to change the way the buttons resize.
Try using GridBagConstraint in this way, hope this will help you.
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame {
Main(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500,500);
JPanel panel1 = new JPanel(new GridBagLayout());
JButton b1,b2;
b1 = new JButton("button 1");
b2 = new JButton("button 2");
panel1.add(b1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
panel1.add(b2, new GridBagConstraints(1, 0, 1, 1, 2.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
add(panel1);
setVisible(true);
}
public static void main(String[]args){
Main m = new Main();
}
}
EDIT
Or change in your code Like this below:
gbc.gridx = 1;
gbc.gridwidth = 1;
panel1.add(b1, gbc);
gbc.gridx = 2;
gbc.gridwidth = 2;
gbc.fill = gbc.HORIZONTAL; //set fill property to HORIZONTAL
gbc.weightx= 2.0;
panel1.add(b2, gbc); //While adding button also add it with gbc
I have this piece of code to add a series of questions and 4 answers for each question.However when i add 3rd question it overwrites the previous row.Can anypne help me to solve this problem.I just need a hint about why it is doing this
package Generators;
/**
*
* #author samim
*/
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class CreateFormFields
{
// Field members
static JPanel panel = new JPanel();
static Integer indexer = 1;
// static List<JLabel> question = new ArrayList<JLabel>();
static List<JTextField> question = new ArrayList<JTextField>();
static List<JTextField> ans1 = new ArrayList<JTextField>();
static List<JTextField> ans2 = new ArrayList<JTextField>();
static List<JTextField> ans3 = new ArrayList<JTextField>();
static List<JTextField> ans4 = new ArrayList<JTextField>();
static List<JTextField> result = new ArrayList<JTextField>();
public static void main(String[] args)
{
// Construct frame
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
frame.setPreferredSize(new Dimension(990, 990));
frame.setTitle("Form Creator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Frame constraints
GridBagConstraints frameConstraints = new GridBagConstraints();
// Construct button
JButton addButton = new JButton("Add");
addButton.addActionListener(new ButtonListener());
// Add button to frame
frameConstraints.gridx = 0;
frameConstraints.gridy = 0;
frame.add(addButton, frameConstraints);
// Construct panel
panel.setPreferredSize(new Dimension(950, 400));
panel.setLayout(new GridBagLayout());
JScrollPane scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setPreferredSize(new Dimension(900, 400));
frameConstraints.gridx = 0;
frameConstraints.gridy = 1;
frame.add(scrollPane, frameConstraints);
// Pack frame
frame.pack();
// Make frame visible
frame.setVisible(true);
}
static class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent arg0)
{
// Clear panel
panel.removeAll();
panel.setPreferredSize(new Dimension(950,panel.getHeight()+200));
// Create label and text field
JTextField jTextField = new JTextField();
JTextField jTextField2 = new JTextField();
JTextField jTextField3 = new JTextField();
JTextField jTextField4 = new JTextField();
JTextField jTextField5 = new JTextField();
JTextField jTextField6 = new JTextField();
question.add(jTextField);
ans1.add(jTextField2);
ans2.add(jTextField3);
ans3.add(jTextField4);
ans4.add(jTextField5);
result.add(jTextField6);
// Create constraints
GridBagConstraints textFieldConstraints = new GridBagConstraints();
GridBagConstraints labelConstraints = new GridBagConstraints();
GridBagConstraints gridans1 = new GridBagConstraints();
GridBagConstraints temp = new GridBagConstraints();
// Add labels and text fields
for(int i = 1; i <= indexer; i++)
{
int R = (int) (Math.random() * 255);
int G = (int) (Math.random() * 255);
int B = (int) (Math.random() * 255);
String total = "rgb(" + R + "," + G + "," + B + ")";
// Label constraints
labelConstraints.gridx = 0;
labelConstraints.gridy = i * 7;
labelConstraints.insets = new Insets(5, 300, 5, 300);
panel.add(new JLabel("<html><font color='" + total + "'>Question " + i + "<font></html>"),
labelConstraints);
temp.gridx = 0;
temp.gridy = i * 8;
temp.insets = new Insets(10, -550, 10, 2);
panel.add(new JLabel("Question :"), temp);
// Text field constraints
textFieldConstraints.fill = 1;//GridBagConstraints.HORIZONTAL;
textFieldConstraints.insets = new Insets(10, -550, 10, 0);
textFieldConstraints.gridy = i * 8;
panel.add(question.get(i - 1), textFieldConstraints);
gridans1.fill = 1;//GridBagConstraints.HORIZONTAL;
gridans1.insets = new Insets(10, -550, 10, 290);
gridans1.gridy = i * 9;
temp.gridy = i * 9;
panel.add(new JLabel("Answer 1 :"), temp);
panel.add(ans1.get(i - 1), gridans1);
gridans1.gridy = i * 10;
temp.gridy = i * 10;
panel.add(new JLabel("Answer 2 :"), temp);
panel.add(ans2.get(i - 1), gridans1);
gridans1.gridy = i * 11;
temp.gridy = i * 11;
panel.add(new JLabel("Answer 3:"), temp);
panel.add(ans3.get(i - 1), gridans1);
gridans1.gridy = i * 12;
temp.gridy = i * 12;
panel.add(new JLabel("Answer 4:"), temp);
panel.add(ans4.get(i - 1), gridans1);
gridans1.gridy = i * 13;
temp.gridy = i * 13;
panel.add(new JLabel("Good Result :"), temp);
panel.add(result.get(i - 1), gridans1);
}
// Align components top-to-bottom
// Increment indexer
indexer++;
panel.updateUI();
}
}
}
Four GridBagConstrains, many components with looping: the performance is poor, the code read style is too complex. It is better you change your design of your code:
While working with group of similar type of component, try enclose them inside another Container Component:
MyQuestionPanel extends JPanel
{
public JLabel questionLab;
public JTextField qAnsField1;
public JTextFeild qAnsField2;
MyQuestionPanel(int questionNo)
{
setLayout(/* GridBagLayout any layout relevant to your design */);
//add your compoenents suing add(component, gridBagConstraint),
//or with relevant add() method e.g., questionLab, qAnsField1, qAnsField2
}
}
Now, assuming that you have root panel which is going to maintain the Question panel(which is container the question label and answer input field), has necessary layout(BoxLayout or other relevant to your design), create a new instance of MyQuestionPanel and add them to the root panel. You don't need to remove all the question panel and re-add them to the root panel on Button Click, as you were doing, rather simply put the root.add(MyQuestionPanel)
You don't need to call updateUI(); in fact you should not in this case, because it will first uninstall all the properties you had of the calling component and then reinstall the UI with extra call revalidate() and repaint(). Just call root.revalidate() and then root.repaint() to reflect the changes for adding and removing component.
If you do these, you will see your code will be much shorter, simpler and nicer. Give it a try.
I want to make an input form in Java so that the user can enter details.
Something like this:
My code
import java.awt.GridLayout;
import javax.swing.*;
class JOptionPaneTest {
public static void main(String[] args) {
String[] items = {"One", "Two", "Three", "Four", "Five"};
JComboBox combo = new JComboBox(items);
JTextField field1 = new JTextField("1234.56");
JTextField field2 = new JTextField("9876.54");
JPanel panel = new JPanel(new GridLayout(0, 1));
panel.add(combo);
panel.add(new JLabel("Field 1:"));
panel.add(field1);
panel.add(new JLabel("Field 2:"));
panel.add(field2);
int result = JOptionPane.showConfirmDialog(null, panel, "Test",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
System.out.println(combo.getSelectedItem()
+ " " + field1.getText()
+ " " + field2.getText());
} else {
System.out.println("Cancelled");
}
}
}
My output form:
I think I must change my layout to something like BorderLayout. Any ideas how to get the look of the form at the top of the question?
Yes, you have to change layout. Have a look at SpringLayout and this example:
(source: sun.com)
String[] labels = {"Name: ", "Fax: ", "Email: ", "Address: "};
int numPairs = labels.length;
//Create and populate the panel.
JPanel p = new JPanel(new SpringLayout());
for (int i = 0; i < numPairs; i++) {
JLabel l = new JLabel(labels[i], JLabel.TRAILING);
p.add(l);
JTextField textField = new JTextField(10);
l.setLabelFor(textField);
p.add(textField);
}
//Lay out the panel.
SpringUtilities.makeCompactGrid(p,
numPairs, 2, //rows, cols
6, 6, //initX, initY
6, 6); //xPad, yPad
SpringLayout works fine for this simple form, but there is third party libraries that has more features. I.e. MiG Layout.
Another way to create a form using GridBagLayout, producing the following result:
Code:
JPanel addressPanel = new JPanel();
Border border = addressPanel.getBorder();
Border margin = new EmptyBorder(10, 10, 10, 10);
addressPanel.setBorder(new CompoundBorder(border, margin));
GridBagLayout panelGridBagLayout = new GridBagLayout();
panelGridBagLayout.columnWidths = new int[] { 86, 86, 0 };
panelGridBagLayout.rowHeights = new int[] { 20, 20, 20, 20, 20, 0 };
panelGridBagLayout.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
panelGridBagLayout.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0,
Double.MIN_VALUE };
addressPanel.setLayout(panelGridBagLayout);
addLabelAndTextField("City:", 0, addressPanel);
addLabelAndTextField("Street:", 1, addressPanel);
addLabelAndTextField("State:", 2, addressPanel);
addLabelAndTextField("Phone:", 3, addressPanel);
addLabelAndTextField("Mail:", 4, addressPanel);
The helper method addLabelAndTextField:
private void addLabelAndTextField(String labelText, int yPos,
Container containingPanel) {
JLabel label = new JLabel(labelText);
GridBagConstraints gridBagConstraintForLabel = new GridBagConstraints();
gridBagConstraintForLabel.fill = GridBagConstraints.BOTH;
gridBagConstraintForLabel.insets = new Insets(0, 0, 5, 5);
gridBagConstraintForLabel.gridx = 0;
gridBagConstraintForLabel.gridy = yPos;
containingPanel.add(label, gridBagConstraintForLabel);
JTextField textField = new JTextField();
GridBagConstraints gridBagConstraintForTextField = new GridBagConstraints();
gridBagConstraintForTextField.fill = GridBagConstraints.BOTH;
gridBagConstraintForTextField.insets = new Insets(0, 0, 5, 0);
gridBagConstraintForTextField.gridx = 1;
gridBagConstraintForTextField.gridy = yPos;
containingPanel.add(textField, gridBagConstraintForTextField);
textField.setColumns(10);
}
You are currently using a GridLayout, which can be fine for your need.
However, you should initialize it with the actual number of rows and columns you will need. In your case:
new GridLayout(0, 2);
0 for rows means there is not limit, and you have 2 columns, one for the labels, and one for the input component. See the Java tutorial for more information on GridLayouts.
(source: sun.com)
Note however that the GridLayout will make all "cells" to be the same size, which can be a problem for the labels.
However, Jonas is right, a SpringLayout is probably more adapted to your need.
You can do this with DesignGridLayout. The following snippet should work (sorry I could not test it I am not on my dev station right now):
DesignGridLayout layout = new DesignGridLayout(panel);
layout.row().grid(streetAddressLabel).add(streetAddressField);
layout.row().grid(cityLabel).add(cityField);
layout.row().grid(stateLabel).add(stateSpinner);
layout.row().grid(zipLabel).add(zipField);
layout.emptyRow();
layout.row().right().add(setAddressButton, clearAddressButton);
Then you would use JDialog (rather than JOptionPane) to display your panel.