3

So, I was using null layout but was told it was a terrible idea and so decided to use GridBagLayout, as it's supposedly the easiest to customise. I'm having trouble with positioning my components, I am really confused as to how I can get a label to the top middle of the screen, my table in the middle, and my login button to the bottom right. Does anyone know how to do this?

Here's my code:

import javafx.geometry.HorizontalDirection;

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

public class Main
{

    JFrame window = new JFrame("PE Fixture");   //JFrame variables

    JPanel container = new JPanel();
    JPanel guestFixturesPanel = new JPanel();
    JPanel loginPanel = new JPanel();
    JPanel adminFixturesPanel = new JPanel();
    JPanel createPanel = new JPanel();

    String[] columns = {"Sport", "Location", "Date", "Result"};
    String[][] data = {{"Football", "AQA Highschool", "12.11.13", "5 - 0"},
            {"Tennis", "Wembley", "26.11.14.", "TBC"}};


    CardLayout cardLayout = new CardLayout();
    GridBagConstraints c = new GridBagConstraints();

    public Main()
    {

        container.setLayout(cardLayout);

        guestFixturesPanel.setLayout(new GridBagLayout());        //GUEST FIXTURES PANEL COMPONENTS

        JButton loginButton = new JButton("Login");
        c.gridx = 0;
        c.gridy = 2;
        c.insets = new Insets(0, 0, 10, 0);
        guestFixturesPanel.add(loginButton, c);
        JTable fixturesTable = new JTable(data, columns)
        {
            public boolean isCellEditable(int data, int columns)
            {
                return false;
            }
        };
        fixturesTable.setPreferredScrollableViewportSize(new Dimension(500, 300));
        fixturesTable.setFillsViewportHeight(true);
        JScrollPane scrollTable = new JScrollPane(fixturesTable);
        c.gridx = 0;
        c.gridy = 0;
        c.ipady = 700;
        c.ipadx = 400;
        guestFixturesPanel.add(scrollTable, c);
        JLabel fixturesLabel = new JLabel("FIXTURES");
        fixturesLabel.setFont(new Font("TimesRoman", Font.PLAIN, 50));
        fixturesLabel.setForeground(Color.WHITE);
        c.gridx = 0;
        c.gridy = 0;
        guestFixturesPanel.add(fixturesLabel, c);

        container.add(guestFixturesPanel, "2");         //LABELS EACH COMPONENT WITH A NUMBER
        container.add(loginPanel, "3");
        container.add(adminFixturesPanel, "4");
        container.add(createPanel, "5");

        guestFixturesPanel.setBackground(Color.DARK_GRAY);      //Colours each panel
        loginPanel.setBackground(Color.DARK_GRAY);
        adminFixturesPanel.setBackground(Color.DARK_GRAY);
        createPanel.setBackground(Color.DARK_GRAY);
        cardLayout.show(container, "1");

        window.add(container);          //Creates the frame of the program.
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setSize(500, 860);
        window.setResizable(false);
        window.setVisible(true);

    }

    public static void main(String[] args)
    {

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main();
            }
        });

    }
}

EDIT:

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

    public class Main
    {
        String[] columns = {"Sport", "Location", "Date", "Result"};
        String[][] data = {{"Football", "AQA Highschool", "12.11.13", "5 - 0"},
                {"Tennis", "Wembley", "26.11.14.", "TBC"}};

        private void createAndShowGUI()
        {
            CardLayout layout = new CardLayout();

            JPanel guestCard = new JPanel(layout);
            JPanel guestTitle = new JPanel(new FlowLayout(FlowLayout.CENTER));               //GUEST TOP PANEL
            JLabel fixturesLabel = new JLabel("FIXTURES");
            fixturesLabel.setFont(new Font("TimesRoman", Font.PLAIN, 50));
            fixturesLabel.setForeground(Color.WHITE);
            guestTitle.add(fixturesLabel);
            JTable fixturesTable = new JTable(data, columns)                                 //GUEST MID PANEL
            {
                public boolean isCellEditable(int data, int columns)
                {
                    return false;
                }
            };
            fixturesTable.setPreferredScrollableViewportSize(new Dimension(350, 450));
            fixturesTable.setFillsViewportHeight(true);
            JScrollPane scrollTable = new JScrollPane(fixturesTable);
            JPanel guestBot = new JPanel(new FlowLayout(FlowLayout.RIGHT));                  //GUEST BOT PANEL
            JButton loginButtonGuest = new JButton("Login");
            guestBot.add(loginButtonGuest);



            JPanel loginCard = new JPanel(layout);                                           //LOGIN TOP PANEL
            JPanel loginTitle = new JPanel(new FlowLayout(FlowLayout.CENTER));
            JLabel loginLabel = new JLabel("LOGIN");
            loginLabel.setFont(new Font("TimesRoman", Font.PLAIN, 50));
            loginLabel.setForeground(Color.WHITE);
            loginTitle.add(loginLabel);

            JPanel container = new JPanel(new BorderLayout(8,8));                           //ADDS CARDS TO CONTAINER
            container.add(guestCard, "2");
            container.add(loginCard, "3");

            guestCard.add(guestTitle, BorderLayout.NORTH);                                  //ADDS COMPONENTS TO CARDS
            guestCard.add(scrollTable, BorderLayout.CENTER);
            guestCard.add(guestBot, BorderLayout.SOUTH);
            loginCard.add(loginTitle, BorderLayout.NORTH);

            container.setBackground(Color.DARK_GRAY);                                       //COLOURS CARDS
            guestTitle.setBackground(Color.DARK_GRAY);
            scrollTable.setBackground(Color.DARK_GRAY);
            guestBot.setBackground(Color.DARK_GRAY);

            layout.show(container, "1");

            JFrame window = new JFrame("PE Fixtures");                                      //CREATES WINDOW
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.getContentPane().add(container);
            window.setSize(400, 700);
            window.setLocationRelativeTo(null);
            window.setResizable(false);
            window.setVisible(true);

        }

        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Main().createAndShowGUI();
                }
            });
        }
    }

ERROR:

"C:\Program Files\Java\jdk1.7.0_51\bin\java" -Didea.launcher.port=7533 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 13.0.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_51\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\rt.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_51\jre\lib\ext\zipfs.jar;C:\Users\Harry\Desktop\Computer Science Projects\PE Fixtures v2.0\out\production\PE Fixtures v2.0;C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 13.0.2\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain Main
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: cannot add to layout: unknown constraint: 2
    at java.awt.BorderLayout.addLayoutComponent(BorderLayout.java:463)
    at java.awt.BorderLayout.addLayoutComponent(BorderLayout.java:424)
    at java.awt.Container.addImpl(Container.java:1120)
    at java.awt.Container.add(Container.java:966)
    at Main.createAndShowGUI(Main.java:48)
    at Main.access$000(Main.java:8)
    at Main$2.run(Main.java:77)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
  • 1
    WindowBuilderPro is a very nice Eclipse plugin that makes building GUI easy. Especially with GridBagLayout. – lanoxx Feb 22 '14 at 00:09
  • 2
    I don't really wan't to use a builder –  Feb 22 '14 at 00:15
  • 1
    GridBagLayout is not a good idea, either, IMHO. Use MiGLayout, it's a newer layout that surpasses all others in both feature set and ease of use. I hardly ever use anything else. FormLayout is a runner up. – Irina Rapoport Feb 22 '14 at 00:48

1 Answers1

6

I am really confused as to how I can get a label to the top middle of the screen, my table in the middle, and my login button to the bottom right.

As you can see GridBagLayout is not the simplest layout manager (too much troubles and not really too much power). To lay out this little amount of components I'd suggest you use a Nested Layout approach:

  • Use BorderLayout to lay out the "main" panel components (label, table and button).
  • Use FlowLayout to center the label inside a top panel and place the button at the right in a bottom panel.

Example

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class Demo {

    private void createAndShowGUI() {

        JLabel label = new JLabel("Title");
        label.setFont(label.getFont().deriveFont(Font.BOLD | Font.ITALIC, 18));
        JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        topPanel.add(label);

        DefaultTableModel model = new DefaultTableModel(new Object[]{"Column # 1", "Column # 2"}, 0);
        model.addRow(new Object[]{"Property # 1", "Value # 1"});
        model.addRow(new Object[]{"Property # 2", "Value # 2"});
        model.addRow(new Object[]{"Property # 3", "Value # 3"});

        JTable table = new JTable(model);
        JScrollPane scrollPane = new JScrollPane(table);            

        JButton button = new JButton("Log In");
        JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        bottomPanel.add(button);

        JPanel content = new JPanel(new BorderLayout(8, 8));
        content.add(topPanel, BorderLayout.NORTH);
        content.add(scrollPane, BorderLayout.CENTER);
        content.add(bottomPanel, BorderLayout.SOUTH);

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(content);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {                
                new Demo().createAndShowGUI();
            }
        });
    }    
}

Screenshot

enter image description here


In addition

For more complex GUI designs you may want to try one of these third-party layout managers suggested in this answer:

Community
  • 1
  • 1
dic19
  • 17,821
  • 6
  • 40
  • 69
  • Hi I did this but decided to change it a little (Check main question), as I didn't want to copy code right off of the Internet. The only thing is I can't position the components, I get an error. The reason I haven't positioned them the same way as you is because I don't want to have a panel for each component, or is that the only way to do it? –  Feb 22 '14 at 17:53
  • Hi there! Glad it helped. The main reason for those panels is because otherwise `BorderLayout` will try to fill the whole available space. F.i.: if you place the button directly like this: `content.add(button, BorderLayout.SOUTH);` then this button will fill the whole south position. Don't worry about how many panels you need to use, `JPanel` is a light-weight container which won't consume too much memory(if this is what concerns you). Please note that after your edit your question doesn't make sense. You should leave it as before so it will help others having similar issues. @HarryKitchener – dic19 Feb 22 '14 at 19:09
  • OK, thanks I'll be sure to use `JPanel`. Also, I'm afraid I no longer have a copy of the previous code for the question, what should I do? –  Feb 22 '14 at 19:17
  • You can "rollback" your question to the previous version. Click the link which says "Edited X hours ago" right under your question. You'll see all the available versions. Find the previous one and click "rollback". @HarryKitchener – dic19 Feb 22 '14 at 19:24
  • Hmm, I just realised an issue. I was using the CardLayout as It was easy to switch between panels, but I can't do this with BorderLayoyt, what should I do? –  Feb 22 '14 at 22:28
  • Unless there's something I can't see, you just need to add the panel with BorderLayout inside a panel with CardLayout. Then you'll have the best of the two layout managers. @HarryKitchener – dic19 Feb 22 '14 at 22:41
  • One more thing, I wan't a back button and a login button both on the bottom. The back button on the left and the login button on the right. how would I do this as when I use to `JPanel` in the same SOUTH position only the back button shows. –  Feb 23 '14 at 12:58
  • 1
    One more time the key is using more panels (it makes me remember this [Portal 2 video](http://www.youtube.com/watch?v=Kyc4JK24EuI) lol). Seriously speaking, you may place a panel with GridLayout at the SOUTH. Within this one place two panels with FlowLayout, the one which will have the back button should be left aligned and the one which will have the log-in button should be right aligned (just like my example shows). Have a look to [A visual guide to Layout Managers](http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html). @HarryKitchener – dic19 Feb 23 '14 at 14:04
  • 1
    Thanks ever so much, also the video made me laugh :D –  Feb 23 '14 at 15:16