MigLayout: push не делает то, что я ожидаю

У меня очень простая проблема с макетом с использованием MigLayout. Вот короткий SSCCE

import java.awt.Color;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

public class LayoutDemo {
    public static void main(final String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel(new MigLayout("insets 0, hidemode 2, debug", "", ""));

        final JLabel[] labels = {new JLabel("Area 1"), new JLabel("Area 2"), new JLabel("Area 3")};
        for (final JLabel l : labels) {
            l.setHorizontalAlignment(JLabel.CENTER);
            l.setBackground(new Color(new Random().nextInt(Integer.MAX_VALUE)));
            l.setOpaque(true);
        }
        panel.add(labels[0], "w 200!");
        panel.add(labels[1], "spany 2, push, grow, wrap");
        panel.add(labels[2], "w 200!, grow, pushy");

        frame.setContentPane(panel);
        frame.setSize(600, 400);
        frame.setVisible(true);
    }
}

который производит следующий вывод:

введите здесь описание изображения

Ячейка Области 1 занимает то же пространство по вертикали, что и Область 3. Но я хочу, чтобы Область 3 максимально отталкивала Область 1. Как я могу это сделать? Единственная фиксированная длина — это ширина двух левых меток.


person brimborium    schedule 09.01.2014    source источник


Ответы (3)


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

Метки Area 1 и Area 2 имеют одну и ту же строку. Ограничение push области метки 2 расширяет текущую строку и столбец. И поскольку две метки имеют одну и ту же строку, это также влияет на область метки 1. Изменение ограничения push области метки 2 на pushx исправляет это. Метка «Область 3» толкается вертикально своим собственным ограничением pushy, и поэтому метка «Область 1» и «Область 2» имеют одинаковую высоту.

В следующем примере кода создается ожидаемый макет:

package com.zetcode;

import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;



public class MigLayoutPushEx extends JFrame {

    public MigLayoutPushEx() {

        initUI();

        setTitle("Gaps");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void initUI() {

        setLayout(new MigLayout("insets 5"));

        final JLabel[] labels = {new JLabel("Area 1"), 
            new JLabel("Area 2"), new JLabel("Area 3")};

        for (final JLabel l : labels) {
            l.setHorizontalAlignment(JLabel.CENTER);
            l.setBorder(BorderFactory.createEtchedBorder());
        }

        add(labels[0], "w 200");
        add(labels[1], "w 200, h 200, spany 2, pushx, grow, wrap");
        add(labels[2], "w 200, grow, pushy");

        pack();
    }    


    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MigLayoutPushEx ex = new MigLayoutPushEx();
                ex.setVisible(true);
            }
        });
    }        
}

Области

person Jan Bodnar    schedule 08.07.2014
comment
Большое спасибо за это разъяснение и решение. Ваше решение мне нравится больше, чем предыдущее, поэтому вы принимаете его. - person brimborium; 08.07.2014

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

http://www.eclipse.org/windowbuilder/

Вы можете легко изменить макет Mig (или любой другой макет), чтобы сделать именно то, что вам нужно.

person Nathan    schedule 09.01.2014
comment
Спасибо за Ваш ответ. Я не большой поклонник графических конструкторов. Я предпочитаю создавать свой собственный код. Но застройщик, которого вы рекомендовали, выглядит хорошо. - person brimborium; 09.01.2014
comment
Нет проблем, как только что предложил @PKopachevsky, возможно, попробуйте использовать конструктор MigLayout... например, frame.getContentPane().setLayout(new MigLayout(, [301px,grow}[53px][173px,grow][10px][118px ,расти], [122.00px,расти][171px,расти][177px,расти])); - person Nathan; 09.01.2014

Укажите ограничения строк в конструкторе MigLayout.

JPanel panel = new JPanel(new MigLayout("insets 0, hidemode 2, debug", "[][]", "[][grow,fill]"));
person PKopachevsky    schedule 09.01.2014
comment
Это работает отлично, спасибо. Хотя я действительно не понимаю, почему мой код этого не делает. Вы можете это объяснить? - person brimborium; 09.01.2014
comment
Я не уверен, что pushy без параметра size заставит компонент заполнить как можно больше места. В технической документации (miglayout.com/whitepaper.html) об этом ничего не говорится. - person PKopachevsky; 10.01.2014
comment
Хорошо, я вижу. Я обычно использую MigLayout только с ограничениями компонентов. Думаю, мне нужно погрузиться в ограничения строк/столбцов. :) Большое спасибо. - person brimborium; 10.01.2014