Могут ли компоненты gridbaglayout заполнять родительский фрейм при изменении размера?

У меня есть JFrame, чей корень JPanel создается с помощью GridBagLayout. Во время выполнения панель заполняется компонентами на основе некоторого описания, а ширина, высота и координаты x,y указываются в описании для использования с полями gridwidth, gridheight, gridx и gridy в GridBagConstraints. Сами компоненты также могут быть JPanel с собственными дочерними компонентами и GridBagConstraints, графический интерфейс описывается в виде дерева, поэтому фрейм заполняется рекурсивно.

Проблема, с которой я сталкиваюсь, заключается в том, что при изменении размера фрейма внутренние компоненты не растягиваются, чтобы заполнить заданную ширину и высоту. Ниже я привел пример кода макета со скриншотами.

import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.util.*;

public class GridBagTest extends JPanel {

    private final GridBagConstraints gbc = new GridBagConstraints();

    public GridBagTest(){

        setLayout(new GridBagLayout());
        add(gbcComponent(0,0,1,2), gbc);    
        add(gbcComponent(1,0,2,1), gbc);            
        add(gbcComponent(1,1,1,1), gbc);            
        add(gbcComponent(2,1,1,1), gbc);            

    }

    //Returns a JPanel with some component inside it, and sets the GBC fields
    private JPanel gbcComponent(int x, int y, int w, int h){

        gbc.gridx = x; 
        gbc.gridy = y;
        gbc.gridwidth = w;
        gbc.gridheight = h;
        gbc.fill = GridBagConstraints.BOTH;
        JPanel panel = new JPanel();
        JTextField text = new JTextField("(" + w + ", " + h + ")");
        panel.setBorder(new TitledBorder("(" + x + ", " + y + ")"));        
        panel.add(text);
        return panel;

    }

    public static void main (String args[]){

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new GridBagTest());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

При запускеПосле растяжения

Мне это нужно, поэтому на рисунке 2 внутренние JPanel, содержащие компоненты, изменяются, чтобы заполнить их соответствующие ширину и высоту на GridBagLayout, в идеале также растягивая их компоненты.


person adnan_252    schedule 13.07.2014    source источник


Ответы (2)


Обычно это происходит из-за того, что вы не устанавливаете ограничения веса и веса.

Пытаться:

gbc.gridx = x; 
gbc.gridy = y;
gbc.gridwidth = w;
gbc.gridheight = h;

// **** add here:
gbc.weightx = 1.0;
gbc.weighty = 1.0;

Это позволит вашему графическому интерфейсу расширяться в направлениях x и y, если это необходимо.

person Hovercraft Full Of Eels    schedule 13.07.2014
comment
Похоже, это работает! Не могу поверить, что я никогда не пробовал его раньше. Теперь есть ли способ, чтобы внутренние панели, содержащие только один компонент, растягивали этот компонент по размеру, чтобы заполнить его? то есть ширина текстовых полей растягивается? - person adnan_252; 13.07.2014
comment
@adnan_252: да, но вам нужно будет предоставить те внутренние менеджеры компоновки JPanels, которые позволяют это, такие как GridBagLayout, или BorderLayout, или... В настоящее время ваши внутренние JPanels используют только FlowLayout по умолчанию, и этот макет довольно прост и не растянуть компоненты. - person Hovercraft Full Of Eels; 13.07.2014
comment
@adnan_252: пожалуйста. И спасибо за публикацию минимального примера программы с вашим questino. - person Hovercraft Full Of Eels; 13.07.2014

Вы можете установить columnWidths и rowHeights при изменении размера вашей JPanel. Посмотрите на этот образец. Я изменил ваш код для двух столбцов:

public GridBagTest(){

    setLayout(new GridBagLayout());
    add(gbcComponent(0,0,1,2), gbc);    
    add(gbcComponent(1,0,1,1), gbc);

    addComponentListener(new java.awt.event.ComponentAdapter() {
        @Override
        public void componentResized(java.awt.event.ComponentEvent evt) {
            GridBagLayout layout = (GridBagLayout) getLayout();
            JPanel panel = (JPanel)evt.getComponent();
            int width = panel.getWidth();
            int height = panel.getHeight();
            int wGap = panel.getInsets().left+panel.getInsets().right;
            int hGap = panel.getInsets().top+panel.getInsets().bottom;
            layout.columnWidths = new int[]{width/2-wGap, width/2-wGap};
            layout.rowHeights = new int[]{height-hGap};
        }
    });

}

В зависимости от количества столбцов и строк вы можете изменить его. Вот результат: введите здесь описание изображения введите здесь описание изображения

person Jeff_Alieffson    schedule 04.01.2016