我有一个非常简单的 JFrame。共有三个主要面板:顶部的横幅图像、左侧的按钮列表以及用户输入登录信息以访问应用程序其余部分的主面板。
我正在使用 GridBagLayout,尽管大多数人都像避免瘟疫一样避免它,但它对我来说非常简单,尽管它确实添加了许多代码行。但是我遇到了这个奇怪的问题,顶行(横幅图像)与底行(按钮和登录面板)重叠。我已经检查并仔细检查并在网上寻找答案,但无法弄清楚我做错了什么。
基本上,底行在整个 JFrame 中垂直居中,而不是在第二个 GridBag 行中。尽管事先已将 BannerPanel 添加到屏幕上,但不知何故,它仍被绘制在上面。我认为这可能与 BannerPanel 的工作方式有关,但我找不到解决方法。
这是它的样子:
https://sphotos-a.xx.fbcdn.net/hphotos-snc7/375898_3720190211823_1073177291_n.jpg
这应该是这样的:
https://sphotos-a.xx.fbcdn.net/hphotos-ash4/314993_3720190291825_1429407717_n.jpg
这是我的代码:
public class LoginWindow extends JFrame implements ActionListener {
final static String unlockCode = "unlock";
ArrayList <User> userlist = new ArrayList <User> ();
User user = null;
// The visible parts of the window
GridBagConstraints gridbag;
JLabel inputLabel, errorLabel, lockedLabel, unlockLabel;
JTextField usernameField, unlockField;
JPasswordField passwordField;
JPanel inputPanel, usernamePanel, passwordPanel, unlockPanel;
public static void main(String[] args) {
LoginWindow win = new LoginWindow ();
win.userlist.add(new User ("username", "password", true));
}
public LoginWindow () {
setTitle("Login");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setBackground(Color.GRAY);
setSize(640, 480);
setResizable(false);
resetGridbag();
// This is where I declare all the JLabels, JPanels, etc
inputLabel = new JLabel ("Secure Login");
inputLabel.setFont(new Font ("SansSerif", Font.BOLD, 24));
inputLabel.setForeground(Color.WHITE);
JLabel usernameLabel = new JLabel ("Username ");
usernameLabel.setForeground(Color.WHITE);
usernameField = new JTextField (10);
usernameField.setActionCommand("Login");
usernameField.addActionListener(this);
usernamePanel = new JPanel ();
usernamePanel.setBackground(Color.GRAY);
usernamePanel.add(usernameLabel);
usernamePanel.add(usernameField);
JLabel passwordLabel = new JLabel ("Password ");
passwordLabel.setForeground(Color.WHITE);
passwordField = new JPasswordField (10);
passwordField.setActionCommand("Login");
passwordField.addActionListener(this);
passwordPanel = new JPanel ();
passwordPanel.setBackground(Color.GRAY);
passwordPanel.add(passwordLabel);
passwordPanel.add(passwordField);
errorLabel = new JLabel ("");
errorLabel.setForeground(Color.WHITE);
lockedLabel = new JLabel ("You've been locked out!");
lockedLabel.setForeground(Color.WHITE);
unlockLabel = new JLabel ("Unlock Code");
unlockLabel.setForeground(Color.WHITE);
unlockField = new JTextField (10);
unlockField.setActionCommand("Unlock");
unlockField.addActionListener(this);
unlockPanel = new JPanel ();
unlockPanel.setBackground(Color.GRAY);
unlockPanel.add(unlockLabel);
unlockPanel.add(unlockField);
JLabel newPassword = new JLabel ("Request a new password");
newPassword.setForeground(Color.WHITE);
JPanel optionPanel = new JPanel ();
optionPanel.setBackground(Color.GRAY);
optionPanel.add(newPassword);
inputPanel = new JPanel ();
inputPanel.setBackground(Color.GRAY);
inputPanel.setLayout(new GridBagLayout ());
// Now I'm going to add them all to the screen
GridBagLayout gbl = new GridBagLayout ();
gbl.columnWeights = new double [] {0.0f, 1.0f};
gbl.rowWeights = new double [] {0.0f, 1.0f};
setLayout(gbl);
gridbag.gridwidth = 2;
gridbag.gridy = 0;
gridbag.fill = GridBagConstraints.HORIZONTAL;
add(new BannerPanel (), gridbag);
gridbag.gridy = 1;
gridbag.gridwidth = 1;
gridbag.anchor = GridBagConstraints.NORTHWEST;
add(optionPanel, gridbag);
gridbag.gridx++;
gridbag.anchor = GridBagConstraints.CENTER;
add(inputPanel, gridbag);
redraw();
setVisible(true);
}
public void resetGridbag () {
gridbag = new GridBagConstraints ();
gridbag.anchor = GridBagConstraints.CENTER;
gridbag.gridx = gridbag.gridy = 0;
}
public void reset () {
inputPanel.removeAll();
resetGridbag();
validate();
repaint();
}
public void redraw () {
reset();
if (user == null || !user.locked()) {
inputPanel.add(inputLabel, gridbag);
gridbag.gridy++;
inputPanel.add(new JLabel (" "), gridbag);
gridbag.gridy++;
inputPanel.add(usernamePanel, gridbag);
gridbag.gridy++;
inputPanel.add(passwordPanel, gridbag);
gridbag.gridy++;
inputPanel.add(new JLabel (" "), gridbag);
gridbag.gridy++;
inputPanel.add(errorLabel, gridbag);
}
else {
inputPanel.add(lockedLabel, gridbag);
gridbag.gridy++;
inputPanel.add(unlockPanel, gridbag);
gridbag.gridy++;
inputPanel.add(errorLabel, gridbag);
errorLabel.setText("");
}
validate();
repaint();
}
public void actionPerformed (ActionEvent e) {
String button = e.getActionCommand();
if (button.equals("Login")) {
boolean usernameMatch = false;
boolean passwordMatch = false;
for (int i = 0; i < userlist.size(); i++) {
if (usernameField.getText().equals(userlist.get(i).username())) {
usernameMatch = true;
user = userlist.get(i);
}
if (new String (passwordField.getPassword()).equals(userlist.get(i).password()))
passwordMatch = true;
}
passwordField.setText("");
if (usernameMatch) {
if (passwordMatch) {
user.unlock();
//new MainWindow ();
dispose();
}
else {
user.loginFail();
if (!user.locked())
errorLabel.setText("Login unsuccessful. " +
user.loginAttempts() + " attempts left!");
else
redraw();
}
}
else
errorLabel.setText("Login unsuccessful.");
validate();
}
else if (button.equals("Unlock")) {
if (unlockField.getText().equals(unlockCode)) {
errorLabel.setText("");
user.unlock();
redraw();
}
else {
errorLabel.setText("Invalid unlock code.");
validate();
}
unlockField.setText("");
}
}
}
class BannerPanel extends JPanel {
Image image;
int width = 0, height = 0;
double ratio = 0.0;
public BannerPanel () {
try {
image = ImageIO.read(BannerPanel.class
.getClassLoader().getResourceAsStream("banner.png"));
}
catch (Exception e) { e.printStackTrace(); }
}
@Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
ratio = (double) getWidth() / image.getWidth(null);
width = getWidth();
height = getImageHeight();
setSize(width, height);
if (image != null) {
g.drawImage(image, 0, 0, width, height, this);
}
}
public int getImageHeight () {
return (int) (image.getHeight(null) * ratio);
}
}
public class User {
String username = "";
String password = "";
boolean superuser = false;
int loginAttempts = 3;
public User (String username, String password, boolean superuser) {
this.username = username;
this.password = password;
this.superuser = superuser;
}
public String username () {
return username;
}
public String password () {
return password;
}
public boolean superuser () {
return superuser;
}
public int loginAttempts () {
return loginAttempts;
}
public void loginFail () {
if (loginAttempts > 0)
loginAttempts--;
}
public boolean locked () {
return (loginAttempts == 0);
}
public void lock () {
loginAttempts = 0;
}
public void unlock () {
loginAttempts = 3;
}
}