GridBagLayout 不能正常工作?

GridBagLayout Not Working Properly?

我在 JFrame 中为我的组件使用 GridBagLayout。我刚开始使用它,但我一直在迷惑自己。我想要的是;左上角的音符,右侧的按钮(垂直),底部的播放按钮。我不确定真正的问题是什么,但你能帮我整理一下吗?

这是我的代码:

package counter.main;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;

public class HomeFrame {

private static JPanel panel;
private static JButton play = new JButton("Play");
private static JPanel p;
File patch = new File(Main.class.getResource("/counter/res/ResourceCounterPatchNotes.txt").getFile());

//private static JLabel text;
public static JLabel greet = new JLabel("", SwingConstants.CENTER);

static JFrame frame = new JFrame("Resource Counter - Home"); {
    frame.setSize(800, 500);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.repaint();
    frame.revalidate();

    createView();
}

private void createView() {
    setIcon();

    panel = new JPanel();
    frame.getContentPane().add(panel);
    p = new JPanel();
    frame.getContentPane().add(p);
    p.setLayout(new FlowLayout(FlowLayout.CENTER, 400, 360));
    play.setPreferredSize(new Dimension(200, 70));
    p.add(play);
    JPanel p2 = new JPanel();
    frame.getContentPane().add(p2);
    p2.setLayout(new GridBagLayout());

    JButton button = new JButton("         Button         ");

    play.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            try {
                Thread.sleep(500);   
            } catch(InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
            SelectionFrame.frame1.setVisible(true);
            frame.setVisible(false);
        }

    });

    JTextArea ta = new JTextArea();
    p2.setBackground(Color.BLACK);
    ta.setForeground(Color.WHITE);
    ta.setFont(new Font("Lucida Sans", Font.PLAIN, 12));

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.insets = new Insets(-150, 5, 5, 30);
    gbc.gridx = 0;
    gbc.gridy = 0;
    p2.add(ta, gbc);
    gbc.gridx = 1;
    gbc.gridy = 0;
    p2.add(button, gbc);
    /*gbc.anchor = GridBagConstraints.SOUTH;
    gbc.gridx = 0;
    gbc.gridy = 2;
    p2.add(play, gbc);*/

    try {
        ta.read(new FileReader(patch), null);
        ta.setEditable(false);
        //p2.add(ta, BorderLayout.WEST);
    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    }


    greet.setFont(new Font( "Dialog", Font.BOLD, 20));
    frame.getContentPane().add(greet, BorderLayout.NORTH);

}

    public void setIcon() {
        frame.setIconImage(Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/counter/res/Iron-Pickaxe-icon.png")));
    }
}

这是我得到的:

你的代码一团糟(抱歉),我可能会花很多时间试图解开你的复合布局,但重新开始会更容易。并不是说您可能不考虑使用复合布局概念,但我认为这就是让您一开始就陷入如此混乱的原因...

所以我基本上创建了一个简化的例子来说明我 "guess" 你的描述要求...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

    public Test() {
        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 GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.gridheight = gbc.REMAINDER;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.BOTH;

            JTextArea patch = new JTextArea(10, 20);

            add(new JScrollPane(patch), gbc);

            gbc = new GridBagConstraints();
            gbc.gridx = 1;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            for (int index = 0; index < 6; index++) {
                add(new JButton("Button #" + index), gbc);
                gbc.gridy++;
            }

            gbc.gridx = 1;
            gbc.anchor = GridBagConstraints.SOUTH;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            add(new JButton("Play >"), gbc);


        }

    }

}

对于布局,最好从笔和纸开始,将您需要的元素组合在一起(例如右侧的按钮),然后设计一个布局方案和视图原型想法...

已更新

1) How can I have it so that there is space between the TextArea and the buttons, and vertical space on the buttons? I tried using the Insets but I haven't arranged the numbers in a correct way yet.

insets 才是正确的做法...

gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(2, 8, 2, 4);
gbc.anchor = GridBagConstraints.NORTH;
for (int index = 0; index < 6; index++) {
    core.add(new JButton("Button #" + index), gbc);
    gbc.gridy++;
}

2) I would like the "Play" button at the center-bottom of the screen, and have it be larger

你 "could" 用 GridBagLayout 做这个,但我决定不这样做,因为如果你不小心设置其他组件的约束,它可能会导致一些问题,所以相反,我使用了 BorderLayoutGridBagLayout.

的组合

要使 "play" 按钮变大,您可以修改字体或调整按钮的边距...

playButton.setMargin(new Insets(12, 12, 12, 12));

取决于你想要的效果

public class TestPane extends JPanel {

    public TestPane() {

        setLayout(new BorderLayout(0, 4));

        JPanel core = new JPanel(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridheight = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.fill = GridBagConstraints.BOTH;

        JTextArea patch = new JTextArea(10, 20);

        core.add(new JScrollPane(patch), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(2, 8, 2, 4);
        gbc.anchor = GridBagConstraints.NORTH;
        for (int index = 0; index < 6; index++) {
            core.add(new JButton("Button #" + index), gbc);
            gbc.gridy++;
        }

        add(core);
        JButton playButton = new JButton("Play >");
        playButton.setMargin(new Insets(12, 12, 12, 12));
        add(playButton, BorderLayout.SOUTH);

    }

}