如何使用 GridBagLayout 和 GridLayout 实现最佳对齐?
How to use GridBagLayout and GridLayout for optimum alignment?
我想在我的程序中试用 GridBagLayout,但遗憾的是我没有清楚地理解它,我也尝试过实现 GridBagLayout,但都给了我不同的问题。让我向您展示代码和输出图片以进一步阐明它:
package iKleen;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
public class ikleenRegister {
JFrame frame;
JPanel phonePanel, fieldPanel, mainPanel;
JLabel name, email, password, address, mobile, l_register;
JTextField nameField, emailField, passwordField, addressField, mobileField, countryCode;
JButton b_register;
GridBagConstraints c;
public void launchGUI()
{
frame = new JFrame("iKleen - Register / Create Free Account");
//phonePanel and its components
phonePanel = new JPanel();
phonePanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
mobileField = new JTextField(8);
countryCode = new JTextField(2);
countryCode.setText("+91");
countryCode.setEnabled(false);
phonePanel.add(countryCode);
phonePanel.add(mobileField);
//fieldPanel and its components
fieldPanel = new JPanel();
fieldPanel.setLayout(new GridBagLayout());
fieldPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
name = new JLabel("Name: ");
email = new JLabel("Email ID: ");
password = new JLabel("Password: ");
address = new JLabel("Address: ");
mobile = new JLabel("Mobile Number: ");
nameField = new JTextField(15);
emailField = new JTextField(15);
passwordField = new JTextField(15);
addressField = new JTextField(20);
c.gridx=0;
c.gridy=0;
fieldPanel.add(name, c);
c.gridx=1;
c.gridy=0;
fieldPanel.add(nameField, c);
c.gridx=0;
c.gridy=1;
fieldPanel.add(email, c);
c.gridx=1;
c.gridy=1;
fieldPanel.add(emailField, c);
c.gridx=0;
c.gridy=2;
fieldPanel.add(password, c);
c.gridx=1;
c.gridy=2;
fieldPanel.add(passwordField, c);
c.gridx=0;
c.gridy=3;
fieldPanel.add(address, c);
c.gridx=1;
c.gridy=3;
fieldPanel.add(addressField, c);
c.gridx=0;
c.gridy=4;
fieldPanel.add(mobile, c);
c.gridx=1;
c.gridy=4;
fieldPanel.add(phonePanel, c);
//mainPanel and its components
mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
Font font = new Font("MS Sans Serif", Font.BOLD, 18);
l_register = new JLabel("Create a free account");
l_register.setFont(font);
l_register.setAlignmentX(Component.CENTER_ALIGNMENT);
b_register = new JButton("Create Account");
b_register.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(l_register);
mainPanel.add(fieldPanel);
mainPanel.add(b_register);
//final frame settings
frame.setContentPane(mainPanel);
frame.pack();
centerFrame();
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void centerFrame() {
Dimension currentScreen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((currentScreen.getWidth() - frame.getWidth()) / 2);
int y = (int) ((currentScreen.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
}
输出:
gridbaglayout
package iKleen;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
public class ikleenRegister {
JFrame frame;
JPanel phonePanel, fieldPanel, mainPanel;
JLabel name, email, password, address, mobile, l_register;
JTextField nameField, emailField, passwordField, addressField, mobileField, countryCode;
JButton b_register;
public void launchGUI()
{
frame = new JFrame("iKleen - Register / Create Free Account");
//phonePanel and its components
phonePanel = new JPanel();
phonePanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
mobileField = new JTextField(15);
countryCode = new JTextField(2);
countryCode.setText("+91");
countryCode.setEnabled(false);
phonePanel.add(countryCode);
phonePanel.add(mobileField);
//fieldPanel and its components
fieldPanel = new JPanel();
fieldPanel.setLayout(new GridLayout(5,2,3,3));
fieldPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
name = new JLabel("Name: ");
email = new JLabel("Email ID: ");
password = new JLabel("Password: ");
address = new JLabel("Address: ");
mobile = new JLabel("Mobile Number: ");
nameField = new JTextField(15);
emailField = new JTextField(15);
passwordField = new JTextField(15);
addressField = new JTextField(15);
fieldPanel.add(name);
fieldPanel.add(nameField);
fieldPanel.add(email);
fieldPanel.add(emailField);
fieldPanel.add(password);
fieldPanel.add(passwordField);
fieldPanel.add(address);
fieldPanel.add(addressField);
fieldPanel.add(mobile);
fieldPanel.add(phonePanel);
//mainPanel and its components
mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
Font font = new Font("MS Sans Serif", Font.BOLD, 18);
l_register = new JLabel("Create a free account");
l_register.setFont(font);
l_register.setAlignmentX(Component.CENTER_ALIGNMENT);
b_register = new JButton("Create Account");
b_register.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(l_register);
mainPanel.add(fieldPanel);
mainPanel.add(b_register);
//final frame settings
frame.setContentPane(mainPanel);
frame.pack();
centerFrame();
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void centerFrame() {
Dimension currentScreen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((currentScreen.getWidth() - frame.getWidth()) / 2);
int y = (int) ((currentScreen.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
}
输出:
gridlayout
在 gridbaglayout 中,数字字段未与其余字段对齐,我希望它们像 jlabels 一样在起点对齐。
而且在gridlayout中,jfields和jlabels之间的差距太大,我尝试了很多解决方案,遗憾的是都无济于事。
你的两次尝试(外面板 GridBagLayout
和 GridLayout
)都非常接近解决方案。
问题是你的 phonePanel
的 FlowLayout
。
在这两种变体中,您都可以通过将其替换为 BorderLayout
(零间隙)来解决问题:
//phonePanel and its components
phonePanel = new JPanel();
phonePanel.setLayout(new BorderLayout(0, 0));
mobileField = new JTextField(15);
countryCode = new JTextField(2);
countryCode.setText("+91");
countryCode.setEnabled(false);
phonePanel.add(countryCode, BorderLayout.WEST);
phonePanel.add(mobileField, BorderLayout.CENTER);
对于您的 GridLayout
变体,执行上述修复:
对于您的 GridBagLayout
变体,执行上述修复。
为了更好看,您可以通过以下方式在组件周围引入一些填充:
c.insets = new Insets(5, 10, 5, 10); // top, left, bottom, right padding
对于 GridBagLayout,更新以下代码行。您正在使用 FlowLayout.CENTER 将手机号码字段移动到面板中间。
phonePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
对于网格布局:
您在 jlabels 和 jtextfield 之间看到的 "gap" 是由于在 GridLayout 中,每个单元格的宽度和高度完全相同。
因此,由于您的 jtextfields 比标签宽,它们将变得更宽以适合它们的单元格。
因此,如果您仍想使用没有间隙的 GridLayout,您可以:
- 尝试限制您的 jtextfields,为构造函数提供不同数量的列(当前最大为 20)。
- 将您的 jlabels 右对齐。这将导致空白间隙被放置在标签的左侧。
当然这些都不是解决方案,它们是一种妥协,因为您的面板会改变外观。
我建议您使用 GridBagLayout,更改您的 "phonePanel" 布局。
如果您不关心您的 phonePanel 是否与其他文本字段具有相同的宽度,您可以使用左对齐的流式布局:
phonePanel.setLayout (new FlowLayout(FlowLayout.LEFT, 0, 0));
你会得到这样的结果:
如果您希望具有相同的宽度,您可以为您的 phonePanel 设置 BorderLayout,在 BorderLayout.WEST 上添加国家代码(以使其具有固定大小)并在中心添加 mobileField(让它占用了所有额外的 space).
phonePanel.setLayout(new BorderLayout());
phonePanel.add(countryCode, BorderLayout.WEST);
phonePanel.add(mobileField, BorderLayout.CENTER);
这是结果:
最后,您可以使用 insets 在标签和文本字段之间插入一个小间隙。
我想在我的程序中试用 GridBagLayout,但遗憾的是我没有清楚地理解它,我也尝试过实现 GridBagLayout,但都给了我不同的问题。让我向您展示代码和输出图片以进一步阐明它:
package iKleen;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
public class ikleenRegister {
JFrame frame;
JPanel phonePanel, fieldPanel, mainPanel;
JLabel name, email, password, address, mobile, l_register;
JTextField nameField, emailField, passwordField, addressField, mobileField, countryCode;
JButton b_register;
GridBagConstraints c;
public void launchGUI()
{
frame = new JFrame("iKleen - Register / Create Free Account");
//phonePanel and its components
phonePanel = new JPanel();
phonePanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
mobileField = new JTextField(8);
countryCode = new JTextField(2);
countryCode.setText("+91");
countryCode.setEnabled(false);
phonePanel.add(countryCode);
phonePanel.add(mobileField);
//fieldPanel and its components
fieldPanel = new JPanel();
fieldPanel.setLayout(new GridBagLayout());
fieldPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
name = new JLabel("Name: ");
email = new JLabel("Email ID: ");
password = new JLabel("Password: ");
address = new JLabel("Address: ");
mobile = new JLabel("Mobile Number: ");
nameField = new JTextField(15);
emailField = new JTextField(15);
passwordField = new JTextField(15);
addressField = new JTextField(20);
c.gridx=0;
c.gridy=0;
fieldPanel.add(name, c);
c.gridx=1;
c.gridy=0;
fieldPanel.add(nameField, c);
c.gridx=0;
c.gridy=1;
fieldPanel.add(email, c);
c.gridx=1;
c.gridy=1;
fieldPanel.add(emailField, c);
c.gridx=0;
c.gridy=2;
fieldPanel.add(password, c);
c.gridx=1;
c.gridy=2;
fieldPanel.add(passwordField, c);
c.gridx=0;
c.gridy=3;
fieldPanel.add(address, c);
c.gridx=1;
c.gridy=3;
fieldPanel.add(addressField, c);
c.gridx=0;
c.gridy=4;
fieldPanel.add(mobile, c);
c.gridx=1;
c.gridy=4;
fieldPanel.add(phonePanel, c);
//mainPanel and its components
mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
Font font = new Font("MS Sans Serif", Font.BOLD, 18);
l_register = new JLabel("Create a free account");
l_register.setFont(font);
l_register.setAlignmentX(Component.CENTER_ALIGNMENT);
b_register = new JButton("Create Account");
b_register.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(l_register);
mainPanel.add(fieldPanel);
mainPanel.add(b_register);
//final frame settings
frame.setContentPane(mainPanel);
frame.pack();
centerFrame();
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void centerFrame() {
Dimension currentScreen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((currentScreen.getWidth() - frame.getWidth()) / 2);
int y = (int) ((currentScreen.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
}
输出: gridbaglayout
package iKleen;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
public class ikleenRegister {
JFrame frame;
JPanel phonePanel, fieldPanel, mainPanel;
JLabel name, email, password, address, mobile, l_register;
JTextField nameField, emailField, passwordField, addressField, mobileField, countryCode;
JButton b_register;
public void launchGUI()
{
frame = new JFrame("iKleen - Register / Create Free Account");
//phonePanel and its components
phonePanel = new JPanel();
phonePanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
mobileField = new JTextField(15);
countryCode = new JTextField(2);
countryCode.setText("+91");
countryCode.setEnabled(false);
phonePanel.add(countryCode);
phonePanel.add(mobileField);
//fieldPanel and its components
fieldPanel = new JPanel();
fieldPanel.setLayout(new GridLayout(5,2,3,3));
fieldPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
name = new JLabel("Name: ");
email = new JLabel("Email ID: ");
password = new JLabel("Password: ");
address = new JLabel("Address: ");
mobile = new JLabel("Mobile Number: ");
nameField = new JTextField(15);
emailField = new JTextField(15);
passwordField = new JTextField(15);
addressField = new JTextField(15);
fieldPanel.add(name);
fieldPanel.add(nameField);
fieldPanel.add(email);
fieldPanel.add(emailField);
fieldPanel.add(password);
fieldPanel.add(passwordField);
fieldPanel.add(address);
fieldPanel.add(addressField);
fieldPanel.add(mobile);
fieldPanel.add(phonePanel);
//mainPanel and its components
mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(25,25,25,25));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
Font font = new Font("MS Sans Serif", Font.BOLD, 18);
l_register = new JLabel("Create a free account");
l_register.setFont(font);
l_register.setAlignmentX(Component.CENTER_ALIGNMENT);
b_register = new JButton("Create Account");
b_register.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(l_register);
mainPanel.add(fieldPanel);
mainPanel.add(b_register);
//final frame settings
frame.setContentPane(mainPanel);
frame.pack();
centerFrame();
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void centerFrame() {
Dimension currentScreen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((currentScreen.getWidth() - frame.getWidth()) / 2);
int y = (int) ((currentScreen.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
}
}
输出: gridlayout
在 gridbaglayout 中,数字字段未与其余字段对齐,我希望它们像 jlabels 一样在起点对齐。 而且在gridlayout中,jfields和jlabels之间的差距太大,我尝试了很多解决方案,遗憾的是都无济于事。
你的两次尝试(外面板 GridBagLayout
和 GridLayout
)都非常接近解决方案。
问题是你的 phonePanel
的 FlowLayout
。
在这两种变体中,您都可以通过将其替换为 BorderLayout
(零间隙)来解决问题:
//phonePanel and its components
phonePanel = new JPanel();
phonePanel.setLayout(new BorderLayout(0, 0));
mobileField = new JTextField(15);
countryCode = new JTextField(2);
countryCode.setText("+91");
countryCode.setEnabled(false);
phonePanel.add(countryCode, BorderLayout.WEST);
phonePanel.add(mobileField, BorderLayout.CENTER);
对于您的 GridLayout
变体,执行上述修复:
对于您的 GridBagLayout
变体,执行上述修复。
为了更好看,您可以通过以下方式在组件周围引入一些填充:
c.insets = new Insets(5, 10, 5, 10); // top, left, bottom, right padding
对于 GridBagLayout,更新以下代码行。您正在使用 FlowLayout.CENTER 将手机号码字段移动到面板中间。
phonePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
对于网格布局:
您在 jlabels 和 jtextfield 之间看到的 "gap" 是由于在 GridLayout 中,每个单元格的宽度和高度完全相同。 因此,由于您的 jtextfields 比标签宽,它们将变得更宽以适合它们的单元格。
因此,如果您仍想使用没有间隙的 GridLayout,您可以:
- 尝试限制您的 jtextfields,为构造函数提供不同数量的列(当前最大为 20)。
- 将您的 jlabels 右对齐。这将导致空白间隙被放置在标签的左侧。
当然这些都不是解决方案,它们是一种妥协,因为您的面板会改变外观。
我建议您使用 GridBagLayout,更改您的 "phonePanel" 布局。 如果您不关心您的 phonePanel 是否与其他文本字段具有相同的宽度,您可以使用左对齐的流式布局:
phonePanel.setLayout (new FlowLayout(FlowLayout.LEFT, 0, 0));
你会得到这样的结果:
如果您希望具有相同的宽度,您可以为您的 phonePanel 设置 BorderLayout,在 BorderLayout.WEST 上添加国家代码(以使其具有固定大小)并在中心添加 mobileField(让它占用了所有额外的 space).
phonePanel.setLayout(new BorderLayout());
phonePanel.add(countryCode, BorderLayout.WEST);
phonePanel.add(mobileField, BorderLayout.CENTER);
这是结果:
最后,您可以使用 insets 在标签和文本字段之间插入一个小间隙。