There are two problems, one, you're calling pack
before you've actually finished building the content. pack
uses the contents preferred size to calculate the size of the window, this would cause you issues as the (potential) size of the content would be different to what you wanted. The fact it works is down to the use of setPreferredSize
you called earlier, which you should avoid doing.
The second issue is the choice of layout manager. GridLayout
will give each component within the container an equal amount of space, horizontally and vertically based on the avaiable space of the parent container.
A better solution might be to use GridBagLayout
, for example.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Example extends JFrame {
//Individual keyboard rows
String firstRow[] = {"~", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "+", "fill", "BackSpace"};
String secondRow[] = {"Tab", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "[", "]", ""};
String thirdRow[] = {"Caps", "A", "S", "D", "F", "G", "H", "J", "K", "L", ":", """, "fill", "fill", "Enter"};
String fourthRow[] = {"Shift", "Z", "X", "C", "V", "B", "N", "M", ",", ".", "?", "blank", "^"};
String fifthRow[] = {"blank", "blank", "fill", "fill", "fill", "fill", "fill", "fill", "fill", "fill", "", "<", "v", ">"};
//Jbuttons corresponding to each individual rows
JButton first[];
JButton second[];
JButton third[];
JButton fourth[];
JButton fifth[];
//Driver main method to start the application
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
new Example().setVisible(true);
}
});
}
// No argument constructor to create frame
public Example() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initWidgets();
}
// Method to initialize frame component
private void initWidgets() {
//set the layout and place component in place and pack it
setLayout(new BorderLayout());
//Various panel for the layout
JPanel jpNorth = new JPanel();
JPanel jpCenter = new JPanel();
JPanel jpKeyboard = new JPanel(new GridBagLayout());
JPanel jpNote = new JPanel();
add(jpNorth, BorderLayout.NORTH);
add(jpNote);
add(jpCenter, BorderLayout.CENTER);
add(jpKeyboard, BorderLayout.SOUTH);
first = new JButton[firstRow.length];
second = new JButton[secondRow.length];
third = new JButton[thirdRow.length];
fourth = new JButton[fourthRow.length];
fifth = new JButton[fifthRow.length];
addKeys(jpKeyboard, 0, firstRow, first);
addKeys(jpKeyboard, 1, secondRow, second);
addKeys(jpKeyboard, 2, thirdRow, third);
addKeys(jpKeyboard, 3, fourthRow, fourth);
addKeys(jpKeyboard, 4, fifthRow, fifth);
pack();
} //end of initWidgets
protected void addKeys(JPanel parent, int row, String[] keys, JButton[] buttons) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = row;
gbc.gridx = 0;
gbc.fill = GridBagConstraints.BOTH;
int gap = 0;
for (int index = 0; index < keys.length; index++) {
String key = keys[index];
if ("blank".equalsIgnoreCase(key)) {
gbc.gridx++;
} else if ("fill".equalsIgnoreCase(key)) {
gbc.gridwidth++;
gap++;
} else {
System.out.println("Add " + key);
JButton btn = new JButton(key);
buttons[index] = btn;
parent.add(btn, gbc);
gbc.gridx += gap + 1;
gbc.gridwidth = 1;
gap = 0;
}
}
}
}//end of class
If you find the answer useful, I would appreciate if you could mark @peeskillet's answer as correct, as he answered first and spotted a few problems I didn't...an upvote would be nice though ;)