【问题标题】:Make a component span multiple cells in GridBagLayout使组件跨越 GridBagLayout 中的多个单元格
【发布时间】:2014-08-17 00:01:58
【问题描述】:

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

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

但是,当我尝试将 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();

    }

}

【问题讨论】:

  • GBC 是基于列的
  • 对于example

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


【解决方案1】:

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

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

我提供了三种解决方案:a) 带有虚拟标签的 GridBagLayout,b) GridBagLayout 带插图和 c) 带间隙的 MigLayout。

解决方案 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 约束创建的,它添加了额外的 组件两侧的空间。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2013-06-16
      • 1970-01-01
      • 2013-03-19
      • 2021-01-24
      • 2021-05-05
      • 1970-01-01
      • 1970-01-01
      • 2015-06-11
      • 1970-01-01
      相关资源
      最近更新 更多