使组件跨越GridBagLayout中的多个单元格

时间:2014-06-26 08:02:43

标签: java swing user-interface layout-manager gridbaglayout

我正在构建一个简单的应用程序,我可以使用它来将一些问题和答案放入其中并将它们保存到不同的数组列表供以后使用(有点像那些有一个问题的测验卡之一我正在构建我的用户界面时,我到达了一堵砖墙,我似乎无法通过。

在下面的代码中我想要" next"按钮跨越多个列并且比文本区域宽

enter image description here

但是当我尝试将widthx变量设置为多列时,似乎没有任何事情发生,有人可以解释为什么会发生这种情况并且可能如何修复它? 感谢

    public class FillingCards extends JPanel implements ActionListener {
    JTextArea question;
    JTextArea answer;
    JButton button;
    ArrayList<String> questions;
    ArrayList<String> answers;
    GridBagConstraints gbc;

    public static void main(String[] args) {
        FillingCards card = new FillingCards();
        card.setupGUI();
        JFrame frame = new JFrame();
        frame.add(BorderLayout.CENTER, card);
        frame.pack();
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setBackground(Color.GRAY);

    }

    public FillingCards() {
        gbc = new GridBagConstraints();
        question = new JTextArea(5, 5);
        answer = new JTextArea(5, 5);
        button = new JButton("next");

    }

    public void setupGUI() {

        this.setLayout(new GridBagLayout());
        gbc.fill = GridBagConstraints.BOTH;
        JScrollPane qs = new JScrollPane(question);
        qs.setPreferredSize(new Dimension(400, 400));
        qs.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        qs.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        gbc.gridx = 1;
        gbc.gridy = 0;
        this.add(qs, gbc);
        gbc.gridx = 1;
        gbc.gridy = 1;
        this.add(new JLabel("Answer: "), gbc);
        JScrollPane as = new JScrollPane(answer);
        as.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        as.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        gbc.gridx = 1;
        gbc.gridy = 2;
        this.add(as, gbc);
        gbc.gridx = 1;
        gbc.gridy = 3;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        this.add(button, gbc);
        button.addActionListener(this);
        questions = new ArrayList<>();
        answers = new ArrayList<>();
        question.setLineWrap(true);
        answer.setLineWrap(true);

    }

    public void startFilling() {
        questions.add(question.getText());
        answers.add(answer.getText());

        question.setText(null);
        answer.setText(null);

    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        startFilling();

    }

}

2 个答案:

答案 0 :(得分:0)

好吧,你不小心碰到了怪癖。虽然布局看起来很简单,但它 我也花了一些时间来解决这个问题。 (顺便说一句,水平拉伸按钮不是最佳的UI设计。)

原因在于管理者的建立方式。如果布局不包含at 连续至少两个组件,不可能跨越组件。 您的布局只包含一列,因此设置widthx&gt; 1确实如此 不行。有两种方法可以解决这个问题:我们可以放置一些 虚拟组件进入布局,或者我们可以在前后放置一些空间 减少宽度的区域。

我提供了三种解决方案:a)带有虚拟标签的GridBagLayout,b)GridBagLayout with insets和c)MigLayout有差距。

Quiz cards

解决方案1 ​​

package com.zetcode;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class FillingCards extends JPanel {

    private JTextArea question;
    private JTextArea answer;
    private JButton button;
    private JLabel label;


    public FillingCards() {


        setupGUI();
    }

    private void setupGUI() {

        question = new JTextArea(12, 22);
        answer = new JTextArea(12, 22);
        button = new JButton("Next");
        label = new JLabel("Answer");   

        question.setBorder(
                BorderFactory.createEtchedBorder()
        );

        answer.setBorder(
                BorderFactory.createEtchedBorder()
        );        

        setLayout(new GridBagLayout());

        GridBagConstraints  gbc = new GridBagConstraints();

        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridwidth = 1;
        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.insets = new Insets(5, 10, 5, 10);

        gbc.gridx = 1;
        gbc.gridy = 0;
        add(question, gbc);

        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.NONE;
        gbc.gridx = 1;
        gbc.gridy = 1;
        gbc.weighty = 0;
        gbc.weightx = 0;
        add(label, gbc);

        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridx = 1;
        gbc.gridy = 2;
        gbc.weightx = 1;
        gbc.weighty = 1;
        add(answer, gbc);

        gbc.gridwidth = 3;
        gbc.weightx = 1;
        gbc.weighty = 0;
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        add(button, gbc);

        gbc.fill = GridBagConstraints.NONE;
        gbc.gridwidth = 1;
        gbc.weighty = 0;
        gbc.weightx = 0;
        gbc.gridx = 0;
        gbc.gridy = 3;
        add(new JLabel("  "), gbc);

        gbc.gridx = 2;
        gbc.gridy = 3;
        add(new JLabel("  "), gbc);  

    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Quiz cards");
        FillingCards card = new FillingCards();
        frame.add(BorderLayout.CENTER, card);
        frame.pack();
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }    
}

在“下一步”按钮下方的第一个和第三个单元格中放置了两个标签。 这不是一个干净的解决方案,主要是为了证明这个问题。

gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 1;
gbc.weighty = 0;
gbc.weightx = 0;
gbc.gridx = 0;
gbc.gridy = 3;
add(new JLabel("  "), gbc);

gbc.gridx = 2;
gbc.gridy = 3;
add(new JLabel("  "), gbc); 

创建两个虚拟标签。这些标签的宽度决定了 左右间隙的宽度。

解决方案2

package com.zetcode;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class FillingCards2 extends JPanel {

    private JTextArea question;
    private JTextArea answer;
    private JButton button;
    private JLabel label;


    public FillingCards2() {


        setupGUI();
    }

    private void setupGUI() {

        question = new JTextArea(12, 22);
        answer = new JTextArea(12, 22);
        button = new JButton("Next");
        label = new JLabel("Answer");   

        question.setBorder(
                BorderFactory.createEtchedBorder()
        );

        answer.setBorder(
                BorderFactory.createEtchedBorder()
        );        

        setLayout(new GridBagLayout());

        GridBagConstraints  gbc = new GridBagConstraints();

        gbc.fill = GridBagConstraints.BOTH;

        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.insets = new Insets(5, 15, 5, 15);

        gbc.gridx = 1;
        gbc.gridy = 0;
        add(question, gbc);

        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.NONE;
        gbc.gridx = 1;
        gbc.gridy = 1;
        gbc.weighty = 0;
        gbc.weightx = 0;
        add(label, gbc);

        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridx = 1;
        gbc.gridy = 2;
        gbc.weightx = 1;
        gbc.weighty = 1;
        add(answer, gbc);

        gbc.insets.left = 5;
        gbc.insets.right = 5;
        gbc.gridwidth = 3;
        gbc.weightx = 1;
        gbc.weighty = 0;
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        add(button, gbc);

    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Quiz cards");
        FillingCards2 card = new FillingCards2();
        frame.add(BorderLayout.CENTER, card);
        frame.pack();
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }    
}

在此示例中,我们使用insets属性创建所需的属性 布局。标签和文本区域的左右插图更宽 那些按钮。

gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.gridwidth = 3;
gbc.weightx = 1;
gbc.weighty = 0;
gbc.gridx = 0;
gbc.gridy = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(button, gbc);

左右插图从15px更改为5px。这样我们就实现了 按钮比其他组件宽。

解决方案3

第三个解决方案是使用MigLayout经理创建的。我们需要更少 用于创建布局的代码。

package com.zetcode;

import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import net.miginfocom.swing.MigLayout;


public class MigLayoutFillingCards extends JFrame {

    public MigLayoutFillingCards() {

        initUI();

        setTitle("Quiz cards");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }


    private void initUI() {

        setLayout(new MigLayout("wrap"));

        JTextArea area1 = new JTextArea();
        JTextArea area2 = new JTextArea();

        area1.setBorder(
                BorderFactory.createEtchedBorder()
        );

        area2.setBorder(
                BorderFactory.createEtchedBorder()
        );                

        JLabel label = new JLabel("Answer");
        JButton btn = new JButton("Next");

        add(area1, "w 250, h 150, grow, push, gap 15 15 0 0");
        add(label, "gap 15 15 0 0");
        add(area2, "w 250, h 150, grow, push, gap 15 15 0 0");
        add(btn, "growx, pushx");

        pack();
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MigLayoutFillingCards ex = new MigLayoutFillingCards();
                ex.setVisible(true);
            }
        });
    }
}

使用gap约束创建了所需的布局,这增加了额外的约束 空间到组件的两侧。

答案 1 :(得分:0)

简短的回答是 - gbc.gridwidth是允许组件跨越多个列的参数。例如,如果您有3列和4行,并且您希望标签占据完整的顶行,则需要为标签指定第一个单元格。并设置gbc.gridwidth = 3;