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

Java 使组件跨越GridBagLayout中的多个单元格,java,swing,user-interface,layout-manager,gridbaglayout,Java,Swing,User Interface,Layout Manager,Gridbaglayout,我正在构建一个简单的应用程序,我可以用它来放置一些问题和答案,并将它们保存到不同的数组列表中供以后使用,就像一张问答卡,一边有问题,另一边有答案。当我构建UI时,我碰到了一堵砖墙,似乎无法通过 在下面的代码中,我希望“下一步”按钮跨越多个列,并且比文本区域更宽 但是,当我试图将widthx变量设置为多列时,似乎什么都没有发生,有人能解释为什么会发生这种情况以及可能如何修复它吗? 谢谢 好吧,你不小心碰到了一个怪癖。虽然布局看起来很简单,但它 我也花了一些时间来思考这个问题。 顺便说一下,水平拉伸

我正在构建一个简单的应用程序,我可以用它来放置一些问题和答案,并将它们保存到不同的数组列表中供以后使用,就像一张问答卡,一边有问题,另一边有答案。当我构建UI时,我碰到了一堵砖墙,似乎无法通过

在下面的代码中,我希望“下一步”按钮跨越多个列,并且比文本区域更宽

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


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

原因在于管理者的构建方式。如果布局不包含在 一行中至少有两个组件,不可能跨越一个组件。 您的布局仅包含一列,因此,设置widthx>1不起作用 不工作。有两种方法可以解决这个问题:我们可以 虚拟组件到布局中,或者我们可以在布局前后放置一些空间 要减小其宽度的区域

我提供了三种解决方案:带虚拟标签的GridBagLayout,b GridBagLayout 带插图和带间隙的MIGC布局

解决方案1

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

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

在本例中,我们使用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);
            }
        });
    }
}
所需的布局是使用间隙约束创建的,这会添加额外的约束
组件两侧的间距。

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

GBC是基于的列。
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);
    }    
}
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);
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);
            }
        });
    }
}