2

So I'm playing around with Swing and GUI's, designing a program in which I have a JPanel containing a 10x10 grid of custom JButtons. I have a horizontal index of numbers from 1-10, and a vertical index of letters from A-J (both JLabels).

I used a BorderLayout with the vertical index to the WEST, and an 11x10 GridLayout nested in the CENTER (why? Because that was the easiest way I could think of to perfect the position of the horizontal index numbers above their corresponding columns of buttons).

I have the first 10 spaces of the 110 space grid filled with numbers to index the columns - and this works fine.

I then used a 11x1 grid to equally space the letters on the vertical index to the WEST, to account for the extra slot of the horizontal index on top of the grid (see picture below).

My problem is: whenever I go to fill the empty space at the top of the vertical grid, it places the new JLabel at the bottom, whether it is placed before the fill loop or after.

Here is the result:

enter image description here

And here is the code I used to fill the loop with a JLabel added before and after the fill loop to show how its being placed at the bottom:

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

public class Test {

 private static void createAndDisplayGUI() {

 // This panel contains the grid layout for the buttons
 JPanel center = new JPanel();
 center.setLayout(new BorderLayout());

 JPanel gridIndexLeft = new JPanel();
 gridIndexLeft.setLayout(new GridLayout(12,1));
 gridIndexLeft.add(new JLabel(" " + 0)); // Added a 0 here before fill loop to show where space should be
 for (int i=0; i<10; i++) {
   gridIndexLeft.add(new JLabel(" " + Character.toString((char)('J' - i))), SwingConstants.CENTER);
 }
 gridIndexLeft.add(new JLabel(" " + 0)); // And again here with same result

 JPanel buttons = new JPanel();
 buttons.setLayout(new GridLayout(11,10));
 for (int i=0; i<10; i++) {
   buttons.add(new JLabel("  " + (10-i)), SwingConstants.CENTER);
 }
 for (int i=0; i<100; i++) {
   buttons.add(new BattleshipButton());
 }

 center.add(gridIndexLeft, BorderLayout.WEST, SwingConstants.CENTER);
 center.add(buttons, BorderLayout.CENTER, SwingConstants.CENTER);

 JPanel content =  new JPanel();
 content.setLayout(new BorderLayout());
 content.add(center, BorderLayout.CENTER);

 JFrame display = new JFrame();
 display.setContentPane(content);
 display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 display.setBackground(Color.GRAY);
 display.setResizable(false);
 display.setSize(300,325);
 display.setLocation(500,190);
 display.setVisible(true);
 }

public static void main(String[] args) {

 try {
   UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName() );
 } catch (Exception e) {
   e.printStackTrace();
 }

 SwingUtilities.invokeLater(new Runnable() {
   public void run() {
     createAndDisplayGUI();
   }
 }); 
 }
}

I know the spacing should be 11x1 to match up, but I've made it 12x1 to show what happens when a new JLabel is added before and after the loop.

Any input would be much appreciated!

SmithNineSix
  • 69
  • 2
  • 8
  • Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This is not a code dump, but an example of what you are doing which highlights the problem you are having. This will result in less confusion and better responses – MadProgrammer Sep 16 '15 at 02:19
  • Okay. I was trying to keep it short and concise but I guess its much more convenient to have SSCCE here for Swing examples. My bad. – SmithNineSix Sep 16 '15 at 02:33
  • The example code makes it easier to place the code into context and see what else might be causing issues, and it allows us to modify it ;) – MadProgrammer Sep 16 '15 at 02:39
  • ***Why*** add components out of the order the layout is expecting? Note that it would be quite possible using a `GridBagLayout`, but I'd use a different approach as detailed in [Making a robust, resizable Swing Chess GUI](http://stackoverflow.com/q/21142686/418556), which adds components in the order that the layout is designed to take them, but keeps a separate array of the 'game place' components for easy adjustment of the game state. – Andrew Thompson Sep 16 '15 at 02:41
  • I appreciate the advice. I'll play with that a bit. The courses I took on Java passed over Swing very briefly so most of what we learned were very basic concepts; never elaborating on bag or map layouts. Most of what I've learned has been on my own by just combining the concepts we were _actually_ taught and a some of what I've had the chance to read about on my own. I do sincerely appreciate any advice or tips on process. – SmithNineSix Sep 16 '15 at 02:53

1 Answers1

5

You problem occurs here...

gridIndexLeft.add(new JLabel(" " + Character.toString((char) ('J' - i))), SwingConstants.CENTER);

SwingConstants.CENTER == 0, it is been interrupted as "add this component at position 0", meaning that anything you added before it is actually been pushed down, why you try to use it when your using a GridLayout, I'm not to sure (maybe you wanted to change the horizontal/vertical position of the label?)

So, when I updated you code to something like...

JPanel gridIndexLeft = new JPanel();
gridIndexLeft.setLayout(new GridLayout(12, 1));
gridIndexLeft.add(new JLabel("-" + 0)); // Added a 0 here before fill loop to show where space should be
for (int i = 0; i < 10; i++) {
    gridIndexLeft.add(new JLabel(" " + Character.toString((char) ('J' - i))));
}
gridIndexLeft.add(new JLabel("+" + 0)); // And again here with same result

It produced...

GridLayout

You can see that -0 is first and +0 is last

Now, if you're really interested, you can do this using a single container and a GridLayout

GridLayout

import java.awt.EventQueue;
import java.awt.GridLayout;
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 GridTest {

    public static void main(String[] args) {
        new GridTest();
    }

    public GridTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridLayout(11, 11));

            for (int row = 0; row < 11; row++) {
                if (row > 0) {
                    add(new JLabel(Character.toString((char) (('A' + row) - 1))));
                } else {
                    add(new JLabel(" "));
                }
                for (int col = 0; col < 10; col++) {
                    if (row == 0) {
                        add(new JLabel(Integer.toString(col + 1)));
                    } else {
                        add(new JButton(" "));
                    }
                }
            }
        }

    }

}

And yes, you can change the horizontal and vertical properties of the JLabels

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Excellent explanation, and thank you for the advice. The reason I was using SwingConstants.CENTER was because earlier I was trying to centre the numbers on the horizontal index above the buttons so they would be in the middle of each JLabel. Guess my positioning was wrong on that one. Thanks so much! – SmithNineSix Sep 16 '15 at 02:44
  • You need to modify the `JLabel` properties directly, `GridLayout` just makes the component fill the entire available cell :P – MadProgrammer Sep 16 '15 at 02:45