Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JButtons inside JPanels with a GridLayout JFrame

I have one JFrame that is set to a GridLayout of size NxN. N is given by the user as a command line at the start of the program. JButtons in an NxN pattern are added to the window in JPanels, set in location by GridLayout (I think).

Does each JButton need its own JPanel to use GridLayout? I'm under the impression that you can set up just one JPanel for all the buttons and set the JPanel to a GridLayout for the JButtons. I want to add another JPanel to the left of the button array to display button clicks (JLabel) and a reset button within that same left JPanel.

Here is (a little of) my code, where N is given by the user, system is my background processes class, and ButtonEvent is the class for ActionListener/actionPerformed:

JFrame window = new JFrame("");
GridLayout layout = new GridLayout(N,N);
window.setLayout(layout);

for (int row = 0; row < N; row++){
    for (int col = 0; col < N; col++){
        JPanel panel = new JPanel();
        JButton b = new JButton ("("+row+","+col+")");
        window.add(b).setLocation(row, col);
        panel.add(b);
        b.addActionListener(new ButtonEvent(b, system, row, col));
        window.add(panel);
    }
}

window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);

And this is what I have (N=4):

http://i.imgur.com/nbQoM.png

Here is (approximately) what I am looking for (N=4):

http://i.imgur.com/SiVWO.png

All I need/want is two (or more) JPanels that are set up roughly like above, and all the layout managers I've tried don't play nice with the GridLayout layout JFrame.

like image 696
Avertheus Avatar asked Apr 29 '12 05:04

Avertheus


3 Answers

Here try this code example:

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

public class LayoutExample extends JFrame
{
    private static final String INITIAL_TEXT = "Nothing Pressed";
    private static final String ADDED_TEXT = " was Pressed";
    private JLabel positionLabel;
    private JButton resetButton;
    private static int gridSize = 4;

    public LayoutExample()
    {
        super("Layout Example");
    }

    private void createAndDisplayGUI()
    {       
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setLayout(new FlowLayout(FlowLayout.LEFT, 20, 20));
        contentPane.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2));

        JPanel leftPanel = new JPanel();
        leftPanel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2));
        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));    
        JPanel labelPanel = new JPanel();
        positionLabel = new JLabel(INITIAL_TEXT, JLabel.CENTER);
        JPanel buttonLeftPanel = new JPanel();
        resetButton = new JButton("Reset");
        resetButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                positionLabel.setText(INITIAL_TEXT);
            }
        });
        labelPanel.add(positionLabel);
        buttonLeftPanel.add(resetButton);
        leftPanel.add(labelPanel);
        leftPanel.add(buttonLeftPanel);

        contentPane.add(leftPanel);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(gridSize, gridSize, 10, 10));
        for (int i = 0; i < gridSize; i++)
        {
            for (int j = 0; j < gridSize; j++)
            {
                JButton button = new JButton("(" + i + ", " + j + ")");
                button.setActionCommand("(" + i + ", " + j + ")");
                button.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent ae)
                    {
                        JButton but = (JButton) ae.getSource();
                        positionLabel.setText(
                            but.getActionCommand() + ADDED_TEXT);                           
                    }
                });
                buttonPanel.add(button);
            }
        }
        contentPane.add(buttonPanel);

        setContentPane(contentPane);
        pack();
        setLocationByPlatform(true);
        setVisible(true);
    }

    public static void main(String[] args)
    {
        if (args.length > 0)
        {
            gridSize = Integer.parseInt(args[0]);
        }
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LayoutExample().createAndDisplayGUI();
            }
        });
    }
}

OUTPUT :

StartAfter Click

like image 125
nIcE cOw Avatar answered Nov 06 '22 20:11

nIcE cOw


Does each JButton need its own JPanel to use GridLayout?

No. Add and setLayout on JFrame don't do what they appear to. JFrame is Top-Level Containers and it is better to organise your content in JPanels.

You should organize your panels in that form:

----JPanel----------------------------|
| ---LeftPanel---  ---ButtonsPanel--- |
| |             |  |                | |
| |             |  |                | |
| |             |  | GridLayout(N,N)| |
| |             |  |                | |
| |             |  |                | |
| ---------------  ------------------ |
---------------------------------------

Then add JPanel to the JFrame. Also put panels in seperate classes:

class BPanel extends JPanel {
    public BPanel() {
        GridLayout layout = new GridLayout(N,N, hgap, vgap);
        setLayout(layout);
        for (int row = 0; row < N; row++){
            for (int col = 0; col < N; col++){
                JButton b = new JButton ("("+row+","+col+")");
                add(b).setLocation(row, col);
                b.addActionListener(new ButtonEvent(b, system, row, col));
            }
        }
    }
}
class LeftPanel extends JPanel {
....
}

class MainFrame extends JFrame {
    public MainFrame() {
        JPanel p = new JPanel();
        p.add(new LeftPanel());
        p.add(newButtonsPanel());
        add(p);
    }
}
like image 28
KrHubert Avatar answered Nov 06 '22 21:11

KrHubert


One advantage to giving each button (or group of buttons) its own panel is that the nested panel can have a different layout. In this example, each nested ButtonPanel has the default FlowLayout, so the button's size remains constant as the enclosing container is resized.

like image 43
trashgod Avatar answered Nov 06 '22 22:11

trashgod