GridBagLayout: равномерно распределенные ячейки

можно ли полностью эмулировать поведение GridLayout с менеджером GridBagLayout?

в принципе, у меня есть сетка 8x8, в которой каждая ячейка должна иметь одинаковую ширину и высоту. GridLayout автоматически сделал это. Но я хочу добавить еще одну строку и столбец в сетку, размер которой не то же самое как и другие. Эта строка / столбец должна занимать все оставшееся пространство ,которое может быть оставлено (потому что доступный размер не может быть одинаковым разделены на 8 клеток). Это вообще возможно, или мне снова придется использовать другой менеджер компоновки?

редактировать

вот простая графика того, что я хочу достичь, упрощенная до всего 4 ячеек: Problem graphic

цветные ячейки-это те, которые я добавил в фактическую сетку (серый), которая имеет ячейки с одинаковой высотой и шириной x. Таким образом, высота и ширина сетки 4*x. Теперь я хочу, чтобы дополнительные ячейки имели необходимую ширину / высоту (minimumSize) плюс остальная часть доступной ширины/высоты от полного размера.

Если размер всей панели изменен, ячейки серой сетки должны снова занять как можно больше места.

5 ответов


set weightx и weighty of GridBagConstraints из фиксированных ячеек в 0 и fill to NONE. Для плавающих ячеек set fill to BOTH, для плавающих ячеек, которые должны расширяться только горизонтально, установите weightx to 1 и для вертикально расширяющихся наборов weighty to 1.

ячейки расширяются, только если они имеют какой-либо контент, поэтому вам нужно заполнить его чем-то. Я выбрал JLabels и установите фиксированные размеры для меток в фиксированных ячейках. На размеры нужно пересчитать размеры и вызов invalidate() для пересчета макета.

вот пример w x h решетки:

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GridBag {
    public static void main(String[] args) {
        final JFrame f = new JFrame("Gridbag Test");
        final Container c = f.getContentPane();
        c.setLayout(new GridBagLayout());

        final Dimension dim = new Dimension(70, 70);
        final int w = 4;
        final int h = 4;
        final JLabel[] yfloating = new JLabel[w];
        final JLabel[] xfloating = new JLabel[h];
        final JLabel[][] fixed = new JLabel[w][h];

        // adding the vertically floating cells
        final GridBagConstraints gc = new GridBagConstraints();
        gc.fill = GridBagConstraints.BOTH;
        gc.weightx = 0.0;
        gc.weighty = 1.0;
        for(int i = 0; i < w; ++i) {
            yfloating[i] = new JLabel("floating " + i);
            yfloating[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
            yfloating[i].setHorizontalTextPosition(JLabel.CENTER);
            yfloating[i].setVerticalTextPosition(JLabel.CENTER);
            gc.gridy = 0;
            gc.gridx = i+1;
            c.add(yfloating[i], gc);
        }

        // adding the horizontally floating cells
        gc.fill = GridBagConstraints.BOTH;
        gc.weightx = 1.0;
        gc.weighty = 0.0;
        for(int i = 0; i < w; ++i) {
            xfloating[i] = new JLabel("floating " + i);
            xfloating[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
            xfloating[i].setHorizontalTextPosition(JLabel.CENTER);
            xfloating[i].setVerticalTextPosition(JLabel.CENTER);
            gc.gridy = i+1;
            gc.gridx = 0;
            c.add(xfloating[i], gc);
        }

        // adding the fixed cells
        gc.fill = GridBagConstraints.NONE;
        gc.weightx = 0.0;
        gc.weighty = 0.0;
        for(int i = 0; i < w; ++i) {
            for(int j = 0; j < h; ++j) {
                fixed[i][j] = new JLabel("fixed " + i);
                fixed[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
                fixed[i][j].setMaximumSize(dim);
                fixed[i][j].setMinimumSize(dim);
                fixed[i][j].setPreferredSize(dim);

                gc.gridx = i+1;
                gc.gridy = j+1;
                c.add(fixed[i][j], gc);
            }
        }

        c.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                final Component comp = e.getComponent();
                final int newSize = Math.min(comp.getHeight() / h, comp.getWidth() / w);
                final Dimension newDim = new Dimension(newSize, newSize);
                for(int i = 0; i < w; ++i) {
                    for(int j = 0; j < h; ++j) {
                        fixed[i][j].setMaximumSize(newDim);
                        fixed[i][j].setMinimumSize(newDim);
                        fixed[i][j].setPreferredSize(newDim);
                    }
                }
                comp.invalidate();
            }
        });

        f.pack();
        f.setVisible(true);
    }
}

Если вы не привязаны к GridBagLayout обязательно, вы должны посмотреть в MigLayout библиотека. Вы можете сделать что-то вроде:

MigLayout layout = new MigLayout(
        "",         // Layout Constraints
        "[10][10][10][10]", // Column constraints
        "[10][10][10][10]");  // Row constraints

все значения устанавливаются в GridBagConstraints.

если вы хотите, чтобы ваша сетка 8x8 исправлена, вы можете установить ipadx и ipady значения.

затем выберите weightx и weighty значения вашей новой строки / столбца в 1.0 и set fill to FULL.

ваша дополнительная строка / столбец будет расширяться с оставшимся пространством.

если вы хотите, чтобы сетка 8x8 также расширялась, это сложнее. Вы можете настроить ipadx и ipady значения в дополнение к weightx и weighty значения. Или сделайте панель для сетки 8x8 и используйте GridLayout там. Использовать GridBagLayout на панели и дополнительной строке / столбце.


есть ли причина, по которой вы не делаете это в JTable? Похоже, именно для этого он и создан. С помощью соответствующего визуализатора ячеек вы можете поместить все, что хотите, в ячейки.

http://www.java2s.com/Code/Java/Swing-Components/TableRowHeaderExample.htm


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

редактировать

didxga напомнил мне в комментариях, что я хотел опубликовать свое решение. Однако, после того, как я выкопал проект и посмотрел на него, я на самом деле не могу опубликовать свое решение, потому что оказывается, что я никогда не создавал его!

Это был проект uni, который закончился официально в середине сентября 2010 года. Мы на самом деле хотели продолжить работу над ним после этого, и, вероятно, поэтому я сказал, что опубликую его (поскольку это была одна вещь, которую я хотел улучшить), но мы никогда не делали этого – к сожалению. Вместо этого я просто оставил эти дополнительные столбец и строку (которая была подразумевается как метка для строк / столбцов btw).

Так что да, мне ужасно жаль, что я не могу опубликовать макет, который делает то, что я изначально хотел...: (может быть, если есть достаточно запроса такого макета, я бы его создал, но на данный момент я не очень хочу снова погружаться в Java layouting ;)