GridBagLayout: равномерно распределенные ячейки
Можно ли полностью эмулировать поведение GridLayout с помощью менеджера GridBagLayout?
В принципе, у меня есть сетка 8x8, в которой каждая ячейка должна иметь одинаковую ширину и высоту. GridLayout автоматически выполнил это. Но я хочу добавить еще одну строку и столбец в сетку, размер которой не совпадает с другим. Эта строка/столбец должна занимать все оставшееся пространство, которое может быть оставлено (поскольку доступный размер не может быть равномерно распределен на 8 ячеек). Возможно ли это, или я снова - должен использовать другой менеджер компоновки?
изменить
Вот простая графика того, чего я хочу достичь, упрощенная до 4-х ячеек:
![Problem graphic]()
Цветные ячейки - это те, которые я добавил в фактическую сетку (серый), в которой есть ячейки с одинаковой высотой и шириной x
. Таким образом, высота и ширина сетки 4*x
. Теперь я хочу, чтобы дополнительные ячейки имели необходимую ширину/высоту (minimumSize) плюс остальную доступную ширину/высоту от полного размера.
Если весь размер панели изменен, серая ячейка сетки должна снова занимать как можно больше места.
Ответы
Ответ 1
Попробовав много разных вещей со встроенными менеджерами макетов, я решил создать собственный менеджер компоновки для этой проблемы. Я еще этого не делал, так как у меня не было времени, чтобы продолжить этот проект, но когда я это сделаю, я обязательно отправлю код менеджера компоновки здесь, чтобы любой, кто интересуется аналогичным решением может использовать его.
изменить
didxga напомнил мне в комментариях, что я хочу опубликовать свое решение. Однако, после выкапывания проекта из-за этого, и, глядя на него, я фактически не могу опубликовать свое решение, потому что, оказывается, я так и не смог его создать!
Это был проект uni, который закончил официальное мероприятие в середине сентября 2010 года. На самом деле мы хотели продолжить работу над ним, поэтому, наверное, поэтому я сказал, что опубликую его (поскольку это было одно, что я хотел улучшить), но мы никогда не обошел это, - к сожалению. Вместо этого я просто исключил лишний столбец и строку (это означалось как метка для строк/столбцов btw).
Так что да, мне ужасно жаль, что я не могу опубликовать макет, который делает то, что я изначально хотел...:( Может быть, если есть достаточно запросов на такой макет, я бы его создал, но на данный момент я не очень хочу нырять в Java layouting снова;)
Ответ 2
установите weightx
и weighty
из GridBagConstraints
фиксированных ячеек на 0
и fill
на NONE
. Для плавающих ячеек установите fill
на BOTH
, для плавающих ячеек, которые должны расширяться только горизонтально, установите weightx
в 1
, а для вертикально расширяющихся установите weighty
на 1
.
Ячейки расширяются только в том случае, если у них есть контент, поэтому вам нужно что-то заполнить. Я выбрал JLabel
и установил фиксированные размеры для меток в фиксированных ячейках. При изменении размера вам необходимо пересчитать размеры и вызвать 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);
}
}
Ответ 3
Если вы не привязаны к GridBagLayout обязательно, вы должны заглянуть в библиотеку MigLayout. Вы можете сделать что-то по строкам:
MigLayout layout = new MigLayout(
"", // Layout Constraints
"[10][10][10][10]", // Column constraints
"[10][10][10][10]"); // Row constraints
Ответ 4
Все значения установлены в GridBagConstraints
.
Если вы хотите, чтобы ваша сетка 8x8 была исправлена, вы можете установить значения ipadx
и ipady
.
Затем установите значения weightx
и weighty
вашей новой строки/столбца на 1.0
и установите fill
на FULL
.
Ваша дополнительная строка/столбец будет расширяться с оставшимся пробелом.
Если вы хотите, чтобы сетка 8x8 также расширялась, это сложнее. Вы можете отрегулировать значения ipadx
и ipady
в дополнение к значениям weightx
и weighty
. Или сделайте панель для сетки 8x8 и используйте там GridLayout
. Используйте GridBagLayout
на панели и дополнительную строку/столбец.
Ответ 5
Есть ли причина, по которой вы не делаете этого в JTable? Похоже на то, что он сделал. С помощью соответствующего рендеринга ячейки вы можете поместить все, что хотите в ячейки.
http://www.java2s.com/Code/Java/Swing-Components/TableRowHeaderExample.htm