I need to align all the fields with the respective labels,
here is my
Several options:
GroupLayout
, illustrated here and here.
BoxLayout
, shown here.
JTable
, discussed here.
Look at the example given for GroupLayout (picture from the link):
Your code should closely resemble the code from the link.
After some findings - MigLayout looks to be the best option for me
Code will be just the following:
JPanel parentPanel = new JPanel(new MigLayout("wrap 2")); //Autowrap after each 2 elements
parentPanel.add(label1);
parentPanel.add(field1);
parentPanel.add(label2);
parentPanel.add(field2);
...
No need to specify indexes by hand or create some huge layout infrastructure - simple code to get conceptually simple result. Please see the QuickStart guide: http://www.miglayout.com/QuickStart.pdf
You can plug it in or directly download from Maven: https://mvnrepository.com/artifact/com.miglayout/miglayout
As a rule of thumb, Never extends the JPanel
/JFrame
unless you are really extending their functionality, always favour composition over inheritance.
For a swing layout manager, I highly recommend miglayout, simple and easy to get started with, you have to download the jar and add it to your CLASSPATH
.
The complete code for prototyping this GUI
Will be just as simple as :
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
/**
* Hello world!
*
*/
public class App {
private JPanel panel;
private JLabel cilentIPLabel= new JLabel();
private JLabel clientPWLabel= new JLabel();
private JTextField clientIPTextField= new JTextField();
private JTextField clientPWTextField= new JTextField();
private JButton printButton = new JButton();
public App() {
initComponents();
}
private void initComponents() {
cilentIPLabel.setText("Client IP :");
clientPWLabel.setText("Client Password :");
printButton.setText("print");
printButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("The ID of the clinet is " + clientIPTextField.getText());
}
});
}
public JPanel getPanel() {
if (panel == null) {
panel= new JPanel(new MigLayout("gap 10","[100]10[100, left, fill, grow]","[][]20[]"));
panel.add(cilentIPLabel);
panel.add(clientIPTextField, "wrap");
panel.add(clientPWLabel);
panel.add(clientPWTextField, "wrap");
panel.add(printButton, "skip, tag apply");
}
return panel;
}
public static void main(String[] args) {
JFrame frame= new JFrame("SO demo");
frame.setSize(400, 150);
frame.setContentPane(new App().getPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Thanks a lot for you help. I modified the code as follows and it worked..
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
// Turn on automatically creating gaps between components that touch
// the edge of the container and the container.
layout.setAutoCreateContainerGaps(true);
GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
hGroup.addGroup(layout.createParallelGroup(Alignment.LEADING).
addComponent(ClientIP).addComponent(ClientPassword).addComponent(Videoname).addComponent(perccomplete).addComponent(PacketsSent).addComponent(Connectiontype).addComponent(noofvideossent));
hGroup.addGroup(layout.createParallelGroup(Alignment.LEADING).
addComponent(ip).addComponent(pass).addComponent(vname).addComponent(percent).
addComponent(pacsent).addComponent(conntype).addComponent(videosend).addComponent(disconnect).addComponent(refresh).addComponent(ok));
layout.setHorizontalGroup(hGroup);
GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
vGroup.addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(ClientIP).addComponent(ip)).addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(ClientPassword).addComponent(pass)).addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(Videoname).addComponent(vname)).addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(perccomplete).addComponent(percent)).addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(PacketsSent).addComponent(pacsent)).addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(Connectiontype).addComponent(conntype)).addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(noofvideossent).addComponent(videosend));
vGroup.addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(disconnect)).addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(refresh)).addGroup(layout.createParallelGroup(Alignment.LEADING).addComponent(ok));
layout.setVerticalGroup(vGroup);
The only reliable way to get the labels and their corresponding fields to line up properly is to put them in the same panel and use a single instance of a layout manager to line them up.
GridLayout
The simplest approach would be to use a two-column Grid layout:
JPanel fieldPane = new JPanel(new GridLayout(0, 2));
fieldPane.add(ClientIP);
fieldPane.add(ip);
fieldPane.add(ClientPassword);
fieldPane.add(pass);
fieldPane.add(Videoname);
fieldPane.add(vname);
fieldPane.add(perccomplete);
fieldPane.add(percent);
fieldPane.add(PacketsSent);
fieldPane.add(pacsent);
fieldPane.add(Connectiontype);
fieldPane.add(conntype);
fieldPane.add(noofvideossent);
fieldPane.add(videosend);
This has the one disadvantage that all the cells will be the same size. Specifically, all the label cells will be the same width as the field cells. This probably won't matter in this specific case, however in the more general case you would want to use a different layout that allows the first column to remain narrow and gives all the remaining width to the second column.
GridBagLayout
Here's how I'd do that with GridBagLayout:
JPanel fieldPane = new JPanel(new GridBagLayout());
Insets insets = new Insets(2, 2, 2, 2);
GridBagConstraints label = new GridBagConstraints(
0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.BASELINE_LEADING, GridBagConstraints.NONE,
insets, 2, 2);
GridBagConstraints value = new GridBagConstraints(
1, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.BASELINE_LEADING, GridBagConstraints.HORIZONTAL,
insets, 2, 2);
fieldPane.add(ClientIP, label);
fieldPane.add(ip, value);
label.gridy++;
value.gridy++;
fieldPane.add(ClientPassword, label);
fieldPane.add(pass, value);
label.gridy++;
value.gridy++;
fieldPane.add(Videoname, label);
fieldPane.add(vname, value);
label.gridy++;
value.gridy++;
fieldPane.add(perccomplete, label);
fieldPane.add(percent, value);
label.gridy++;
value.gridy++;
fieldPane.add(PacketsSent, label);
fieldPane.add(pacsent, value);
label.gridy++;
value.gridy++;
fieldPane.add(Connectiontype, label);
fieldPane.add(conntype, value);
label.gridy++;
value.gridy++;
fieldPane.add(noofvideossent, label);
fieldPane.add(videosend, value);
Because I use GridBagLayout a lot, I subclassed GridBagConstraints to make my life a little easier. My subclass has, amongst others, the following method:
public SuperGBC at(int x, int y) {
gridx = x;
gridy = y;
return this;
}
It has similar methods anchor()
, fill()
and insets()
for initialising itself without having to specify all values. This makes the above code somewhat more compact:
JPanel fieldPane = new JPanel(new GridBagLayout());
Insets insets = new Insets(2, 2, 2, 2);
SuperGBC label = new SuperGBC()
.anchor(SuperGBC.BASELINE_LEADING)
.insets(insets);
SuperGBC value = new SuperGBC()
.anchor(SuperGBC.BASELINE_LEADING)
.insets(insets)
.fill(GridBagConstraints.HORIZONTAL, 0.0, 0.0);
fieldPane.add(ClientIP, label.at(0, 0));
fieldPane.add(ip, value.at(1, 0));
fieldPane.add(ClientPassword, label.at(0, 1));
fieldPane.add(pass, value.at(1, 1));
fieldPane.add(Videoname, label.at(0, 2));
fieldPane.add(vname, value.at(1, 2));
fieldPane.add(perccomplete, label.at(0, 3));
fieldPane.add(percent, value.at(1, 3));
fieldPane.add(PacketsSent, label.at(0, 4));
fieldPane.add(pacsent, value.at(1, 4));
fieldPane.add(Connectiontype, label.at(0, 5));
fieldPane.add(conntype, value.at(1, 5));
fieldPane.add(noofvideossent, label.at(0, 6));
fieldPane.add(videosend, value.at(1, 6));