JFrame GridBagLayout 组件定位

3

所以,我之前使用的是null layout(空布局),但被告知这是一个糟糕的想法,因此决定使用GridBagLayout(网格包布局),因为它被认为是最容易自定义的。我在组件定位方面遇到了问题,我真的很困惑如何将标签放在屏幕顶部中间,将表格放在中间,将登录按钮放在右下角。有谁知道怎么做吗?

以下是我的代码:

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();
            }
        });

    }
}

编辑:

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();
                }
            });
        }
    }

错误:

"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是一个非常好用的Eclipse插件,可以轻松构建GUI界面,特别是在使用GridBagLayout时。 - lanoxx
2
我不太想使用构建器。 - user3255328
1
GridBagLayout在我看来也不是一个好的选择。使用MiGLayout,它是一种新的布局方式,在功能集和易用性方面都超越了其他所有布局方式。我几乎从不使用其他任何布局方式。FormLayout是一个次选项。 - Irina Rapoport
1个回答

6
我很困惑如何把标签放到屏幕顶部中间,将表格放在中间,将登录按钮放到右下角。如您所见,GridBagLayout不是最简单的布局管理器(太麻烦而且并没有太多优势)。为了布置这些组件,我建议您使用嵌套布局方法:
  • 使用BorderLayout来布置“主”面板组件(标签、表格和按钮)。
  • 使用FlowLayout将标签居中放置在顶部面板内,并在底部面板中将按钮放置在右侧。

示例

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();
            }
        });
    }    
}

屏幕截图

enter image description here


此外

对于更复杂的GUI设计,您可能想尝试this answer中建议的其中一个第三方布局管理器:


嗨,我已经完成了这个任务,但是在查看主要问题后决定稍作修改,因为我不想直接复制互联网上的代码。唯一的问题是我无法定位组件,出现了一个错误。我没有按照您的方式将它们定位的原因是我不想为每个组件都创建一个面板,或者说那是唯一的方法吗? - user3255328
好的,谢谢。我会确保使用 JPanel。另外,很抱歉我不再拥有之前问题的代码副本,我该怎么办? - user3255328
除非有我看不到的东西,否则您只需要在一个使用CardLayout的面板内添加一个使用BorderLayout的面板。然后您就可以同时拥有这两种布局管理器的优点了。@HarryKitchener - dic19
1
再说一遍,关键是使用更多的面板(这让我想起了这个Portal 2视频 哈哈)。严肃地说,您可以在SOUTH位置放置一个GridLayout面板。在此面板中放置两个FlowLayout面板,其中一个将具有后退按钮,应左对齐,另一个将具有登录按钮,应右对齐(就像我的示例所示)。请查看布局管理器的可视化指南。@HarryKitchener - dic19
1
非常感谢,视频也让我笑了:D - user3255328
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接