title: Java GridBagLayout: Rows are overlapping
body: <p>I have a pretty simple JFrame. There are three main panels: the banner image at the top, a list of buttons on the left-hand side, and the main panel where the user will input his login information to access the rest of the application.</p>
  
  <p>I'm using a GridBagLayout, and despite most people avoiding it like the plague, it's very straightforward to me, though it does add many lines of code into the mix. However I'm getting this strange problem where the top row (banner image) is overlapping the bottom row (button and login panels). I've checked and double-checked and looked all over the web for an answer but can't figure out what I'm doing wrong.</p>
  
  <p>Basically the bottom row is vertically centered in the JFrame as a whole, and not in the second GridBag row as it should. And somehow the BannerPanel is being drawn on top of that, despite being added to the screen beforehand. I think it may have something to do with the way the BannerPanel works but I for one can't find a workaround.</p>
  
  <p>This is what it looks like:</p>
  
  <p><a href="https://sphotos-a.xx.fbcdn.net/hphotos-snc7/375898_3720190211823_1073177291_n.jpg" rel="nofollow">https://sphotos-a.xx.fbcdn.net/hphotos-snc7/375898_3720190211823_1073177291_n.jpg</a></p>
  
  <p>This is what it SHOULD look like:</p>
  
  <p><a href="https://sphotos-a.xx.fbcdn.net/hphotos-ash4/314993_3720190291825_1429407717_n.jpg" rel="nofollow">https://sphotos-a.xx.fbcdn.net/hphotos-ash4/314993_3720190291825_1429407717_n.jpg</a></p>
  
  <p>Here's my code:</p>
  
  <pre><code>public class LoginWindow extends JFrame implements ActionListener {
      final static String unlockCode = "unlock";
      ArrayList &lt;User&gt; userlist = new ArrayList &lt;User&gt; ();
      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 &lt; 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 &gt; 0)
              loginAttempts--;
      }
  
      public boolean locked () {
          return (loginAttempts == 0);
      }
  
      public void lock () {
          loginAttempts = 0;
      }
  
      public void unlock () {
          loginAttempts = 3;
      }
  }
  </code></pre>