I am making an example application just to learn basics. I am having a problem where I have 3 JTextField
s and when I launch the application the bottom 2 JTextField
s do not show up, but the first one which has the focus, does. But only a fraction of the final size i intend. When I click on them however or begin to type in the fields they expand to the size i originally intended.
They are all in the correct location though they are showing up incorrectly at launch. Any ideas?
package password;
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.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class password implements ActionListener{
static int width = 220, height = 250;
JPanel textPanel, panelForTextFields, completionPanel;
JLabel serviceLabel, usernameLabel, passwordLabel;
JTextField serviceField, usernameField, passwordField;
JButton Submit;
public JPanel setupPane (){
// We create a bottom JPanel to place everything on.
JPanel mainPanel = new JPanel();
mainPanel.setLayout(null);
textPanel = new JPanel();
textPanel.setLayout(null);
textPanel.setLocation(0, 0);
textPanel.setSize(width, height);
mainPanel.add(textPanel);
panelForTextFields = new JPanel();
panelForTextFields.setLayout(null);
panelForTextFields.setLocation(0, 0);
panelForTextFields.setSize(width, height);
mainPanel.add(panelForTextFields);
//---------------------------------------------------------------------------------------------------------------------------------
// Service text field and label
//---------------------------------------------------------------------------------------------------------------------------------
serviceLabel = new JLabel("Service:");
serviceLabel.setLocation(60, 0);
serviceLabel.setSize(80, 40);
textPanel.add(serviceLabel);
serviceField = new JTextField();
serviceField.setLocation(60, 30);
serviceField.setSize(100, 20);
panelForTextFields.add(serviceField);
//---------------------------------------------------------------------------------------------------------------------------------
// Username text field and label
//---------------------------------------------------------------------------------------------------------------------------------
usernameLabel = new JLabel("Username:");
usernameLabel.setLocation(60, 45);
usernameLabel.setSize(80, 40);
textPanel.add(usernameLabel);
usernameField = new JTextField();
usernameField.setLocation(60, 75);
usernameField.setSize(100, 20);
panelForTextFields.add(usernameField);
//---------------------------------------------------------------------------------------------------------------------------------
// Password text field and label
//---------------------------------------------------------------------------------------------------------------------------------
passwordLabel = new JLabel("Password:");
passwordLabel.setLocation(60, 90);
passwordLabel.setSize(80, 40);
textPanel.add(passwordLabel);
passwordField = new JTextField();
passwordField.setLocation(60, 120);
passwordField.setSize(100, 20);
panelForTextFields.add(passwordField);
//---------------------------------------------------------------------------------------------------------------------------------
// Submit button
//---------------------------------------------------------------------------------------------------------------------------------
Submit = new JButton("Submit");
Submit.setLocation(60, 165);
Submit.setSize(100, 20);
panelForTextFields.add(Submit);
Submit.addActionListener(this);
return mainPanel;
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if(source == Submit) {
JOptionPane.showMessageDialog(null," information added.","Success!", JOptionPane.PLAIN_MESSAGE);
}
}
private static void password() {
JFrame mainF = new JFrame("Password Application");
password demo = new password();
mainF.setContentPane(demo.setupPane());
mainF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainF.setSize(width, height);
mainF.setResizable(false);
mainF.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
password();
}
});
}
}
Look at your example as a lesson of how not to build your layouts.
Absolute positioning cannot cope with various challenges that Java GUI applications face:
Therefore, programmers need to use layout managers. Over the years, multiple layout managers were created for Swing. I recommend the following three (in that particular order):
MigLayout
and FormLayout
are third-party managers. Therefore, we need to
download and add their libraries to our projects. These three managers are most
flexible and powerful of all managers.
I create your simple layout with all these three managers.
MigLayout
MigLayout
has a rich set of tools to build the required layout.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
public class MigLayoutPassword extends JFrame {
public MigLayoutPassword() {
initUI();
setTitle("Password application");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
JPanel pnl = new JPanel(new MigLayout("wrap 2, ins dialog",
"[right][grow]"));
JLabel serviceLbl = new JLabel("Service:");
JLabel userNameLbl = new JLabel("User name:");
JLabel passwordLbl = new JLabel("Password:");
JTextField field1 = new JTextField(10);
JTextField field2 = new JTextField(10);
JPasswordField field3 = new JPasswordField(10);
pnl.add(serviceLbl);
pnl.add(field1, "growx");
pnl.add(userNameLbl);
pnl.add(field2, "growx");
pnl.add(passwordLbl);
pnl.add(field3, "growx");
add(pnl);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MigLayoutPassword ex = new MigLayoutPassword();
ex.setVisible(true);
}
});
}
}
Note that there is no positioning, no explicit size setting of components. This is handled by the manager. There are only a few lines that do the layout. Changes to the layout are done easily and quickly.
JPanel pnl = new JPanel(new MigLayout("wrap 2, ins dialog",
"[right][grow]"));
Note the dialog
keyword. This keyword is translated to standard space around the
borders for the current platform.
GroupLayout
In constrast to MigLayout
, GroupLayout
has only a few tools to influence the
layout. However, it is suprisingly powerful. In this manager, we define the
layout using groups of components for each dimension separately.
package com.zetcode;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.BASELINE;
import static javax.swing.GroupLayout.Alignment.TRAILING;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class GroupLayoutPassword extends JFrame {
public GroupLayoutPassword() {
initUI();
setTitle("Password application");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
JLabel serviceLbl = new JLabel("Service:");
JLabel userNameLbl = new JLabel("User name:");
JLabel passwordLbl = new JLabel("Password:");
JTextField field1 = new JTextField(10);
JTextField field2 = new JTextField(10);
JTextField field3 = new JTextField(10);
gl.setAutoCreateGaps(true);
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup(TRAILING)
.addComponent(serviceLbl)
.addComponent(userNameLbl)
.addComponent(passwordLbl))
.addGroup(gl.createParallelGroup()
.addComponent(field1)
.addComponent(field2)
.addComponent(field3))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup(BASELINE)
.addComponent(serviceLbl)
.addComponent(field1))
.addGroup(gl.createParallelGroup(BASELINE)
.addComponent(userNameLbl)
.addComponent(field2))
.addGroup(gl.createParallelGroup(BASELINE)
.addComponent(passwordLbl)
.addComponent(field3))
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
GroupLayoutPassword ex = new GroupLayoutPassword();
ex.setVisible(true);
}
});
}
}
FormLayout
To create this simple layout, I have used the high-level DefaultFormBuilder
.
For more complicated layouts, we would need to go without this (or similar)
builder.
package com.zetcode;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.FormLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class FormLayoutPassword extends JFrame {
public FormLayoutPassword() {
initUI();
setTitle("Password application");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
FormLayout fl = new FormLayout(
"r:p, $rg, p:g", // columns
""); // rows
DefaultFormBuilder builder = new DefaultFormBuilder(fl);
builder.border(Borders.DIALOG);
JTextField field1 = new JTextField(10);
JTextField field2 = new JTextField(10);
JPasswordField field3 = new JPasswordField(10);
builder.append("&Service: ", field1);
builder.nextLine();
builder.append("&User name: ", field2);
builder.nextLine();
builder.append("&Password: ", field3);
builder.nextLine();
JPanel pnl = builder.getPanel();
setContentPane(pnl);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
FormLayoutPassword ex = new FormLayoutPassword();
ex.setVisible(true);
}
});
}
}
Again, we see no explicit positioning or setting size of components or gaps.
FormLayout fl = new FormLayout(
"r:p, $rg, p:g", // columns
""); // rows
All three managers use the concept of related gaps, specified here
as $rg
. A related gap is an
abstraction over a rigid pixel gap size. (A rigid gap specified in pixels is
hardware and OS dependent.)