1

I'm coding in Java Swing and for some reason, when I add two elements to a gridlayout, they both assume the same position. I have tried simplifying it into something that would not fail and then building up from there, but alas, it's still not working.

The misbehaving code within the program is:

        bodyPanelMain.setLayout(new GridLayout(4, 1, 10, 10));
        JTextArea one = new JTextArea("Hi");
        one.setLineWrap(true);
        one.setSize(100, 100);
        JTextArea two = new JTextArea("Goodbye");
        two.setLineWrap(true);
        two.setSize(100, 100);
        bodyPanelMain.add(one);
        bodyPanelMain.add(two);
        bodyPanelMain.repaint();

If I make JTextArea's width 200 and background a different color, it's clear that it's visible behind it, so it's most certainly adding all the proper elements, their positions are just wrong.

EDIT: Here's a very very short version of what I am trying to do.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class minimessageboard extends Applet implements ActionListener {

JPanel mainPanel;
JPanel buttonPanel;
JButton announcements, websites;
JPanel bodyPanel, bodyPanelMain;

public minimessageboard() {
    this.setSize(600, 400);

    mainPanel = new JPanel(new BorderLayout());
    mainPanel.setPreferredSize(new Dimension(this.getWidth(), this.getHeight()));
    this.add(mainPanel);

    buttonPanel = new JPanel(new GridLayout(6, 1, 10, 10));
    mainPanel.add(buttonPanel, BorderLayout.WEST);

    announcements = new JButton("Announcements");
    this.formatButton(announcements);
    announcements.setActionCommand("announcements");
    buttonPanel.add(announcements);

    websites = new JButton("Websites");
    this.formatButton(websites);
    websites.setActionCommand("websites");
    buttonPanel.add(websites);

    bodyPanel = new JPanel(new BorderLayout());
    bodyPanel.setSize(200, 500);
    bodyPanel.setPreferredSize(new Dimension(200, 500));
    mainPanel.add(bodyPanel, BorderLayout.CENTER);

    bodyPanelMain = new JPanel(new BorderLayout());
    bodyPanel.add(bodyPanelMain, BorderLayout.CENTER);
    bodyPanelMain.setLayout(new GridLayout(4, 1, 10, 10));
    JButton one = new JButton("Roar");
    bodyPanelMain.add(one);
    bodyPanelMain.revalidate();
    bodyPanelMain.repaint();
}

public static void main(String args[]) {
    JFrame overall = new JFrame(); 
    overall.pack();
    overall.setVisible(true);
    overall.add(new minimessageboard());
}

public void formatButton(JButton b){
    b.setPreferredSize(new Dimension(150, 33));
    b.addActionListener(this);
}

public void actionPerformed(ActionEvent arg0) {
    String action = arg0.getActionCommand();
    bodyPanelMain.removeAll();
    if (action.equals("websites")){
        System.out.println("Fires!");
        bodyPanelMain.setLayout(new GridLayout(4, 1, 10, 10));
        JButton one = new JButton("Hi");
        JButton two = new JButton("Goodbye");
        bodyPanelMain.add(one);
        bodyPanelMain.add(two);
        bodyPanelMain.revalidate();
    }
    bodyPanelMain.repaint();
}
}

Basically, when you click on websites, "Hi" and "Bye" should show up. If I move the code within the block in the websites if statement (if (action.equals("websites")) up to the original constructor, it appears perfectly fine. The code outputs "Fires!", so I am 100% certain it gets to that part. For note, I changed it from JTextArea to JButton because I will be using JButtons, not JTextArea.

  • I think the issue is you aren't positioning your elements (unless this GridLayout construct does that for you, I'm not familiar with Java). – Elliot Bonneville Apr 07 '12 at 15:25
  • @Elliott: I think just the opposite is true. – Hovercraft Full Of Eels Apr 07 '12 at 15:31
  • 1
    Don't set the size of a JTextArea as it won't work well when your text extends beyond the text area size and you find that it just won't scroll. Instead set the preferred row and column values, and then let the JTextArea size itself. On to your problem: are you adding these components after the GUI has rendered itself? If so, do you call `revalidate()` on the bodyPanelMain after it receives the JTextAreas? If this doesn't help, consider creating and posting an [sscce](http://sscce.org). – Hovercraft Full Of Eels Apr 07 '12 at 15:34
  • *"..you aren't positioning your elements (unless this GridLayout construct does that for you.."* Sizing and positioning components is what layout managers do! Some accept layout constraints when adding components, but `GridLayout` does not. – Andrew Thompson Apr 07 '12 at 15:37
  • @HovercraftFullOfEels In the rare examples I've done that had dynamically added components, I've never needed to call `revalidate()`. The [nested layout example](http://stackoverflow.com/a/5630271/418556) for example, simply calls `validate()`. – Andrew Thompson Apr 07 '12 at 15:41

1 Answers1

3

Don't set the size of a JTextArea as it won't work well when your text extends beyond the text area size and you find that it just won't scroll. Instead set the preferred row and column values, and then let the JTextArea size itself. On to your problem: are you adding these components after the GUI has rendered itself? If so, do you call revalidate() on the bodyPanelMain after it receives the JTextAreas? If this doesn't help, consider creating and posting an sscce.

For example, this works fine for me:

import java.awt.GridLayout;
import javax.swing.*;

public class SwingFoo {
   private static final int ROWS = 10;
   private static final int COLS = 16;

   private static void createAndShowGui() {
      JPanel bodyPanelMain = new JPanel();
      bodyPanelMain.setLayout(new GridLayout(4, 1, 10, 10));
      JTextArea one = new JTextArea("Hi", ROWS, COLS);
      one.setLineWrap(true);
      // one.setSize(100, 100);
      JTextArea two = new JTextArea("Goodbye", ROWS, COLS);
      two.setLineWrap(true);
      // two.setSize(100, 100);
      bodyPanelMain.add(new JScrollPane(one));
      bodyPanelMain.add(new JScrollPane(two));
      // bodyPanelMain.repaint();

      JFrame frame = new JFrame("SwingFoo");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(bodyPanelMain);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • I tried adding in the changes you mentioned (removing size and instead, putting it in the constructor parameter of the text boxes), but that made my text boxes disappear. SetSize was what made them visible. setting them as visible manually does not make them appear either as their size is 0, 0. I also called revalidate and that did not work. – user1319243 Apr 07 '12 at 16:07
  • @user1319243: then do what I've done above -- create and post an [SSCCE](http://sscce.org) that shows your problem. – Hovercraft Full Of Eels Apr 07 '12 at 16:08
  • OK, I've found what I think is the issue... If I move my code to the constructor of the object, it will work perfectly. The way I want it, though, is that you click on a button and bodyPanelMain is restructured to include all of the components in my code. In the beginning, I bodyPanelMain.removeAll, which means there are no other components than the new ones. Why would later changing bodyPanelMain break it? – user1319243 Apr 07 '12 at 16:35
  • @user1319243: it all depends on how you code this. Since we haven't seen more than a snippet, it's hard to tell what you're doing wrong. – Hovercraft Full Of Eels Apr 07 '12 at 16:37
  • I've edited my original post to include the SSCCE you requested. Thanks for your help so far. – user1319243 Apr 08 '12 at 03:37
  • @user1319243: Don't mix AWT with Swing components needlessly. Your GUI subclasses *Applet* when it should subclass *JApplet*. – Hovercraft Full Of Eels Apr 08 '12 at 03:48
  • Holy bjesus, @Hovercraft. You just fixed it. Thankyouthankyouthankyou – user1319243 Apr 08 '12 at 03:59