Пожалуйста, помогите мне разобраться в проблемах выравнивания BoxLayout - PullRequest
5 голосов
/ 18 апреля 2011

Я пытаюсь создать очень простое окно, используя Java Layouts.У меня есть три элемента: кнопка, индикатор выполнения и метка.Кнопка должна быть вертикально отцентрирована, индикатор выполнения должен занимать всю ширину, а метка должна быть выровнена по левому краю.

Вот некоторый код (предположим, что pane - это панель содержимого JFrame, а кнопка, progressBar и метка были созданы ранее):

BoxLayout layout = new BoxLayout(pane, BoxLayout.Y_AXIS);
pane.setLayout(layout);
button.setAlignmentX(Component.CENTER_ALIGNMENT);
pane.add(button);
progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
pane.add(progressBar);
label.setAlignmentX(Component.LEFT_ALIGNMENT);
pane.add(label);

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

Я просто не понимаю, что происходит.Можете ли вы дать мне подсказку?

Ответы [ 5 ]

7 голосов
/ 18 апреля 2011

BoxLayout не может обрабатывать различные выравнивания: см. http://download.oracle.com/javase/tutorial/uiswing/layout/box.html

цитата из этой статьи: «В общем, все компоненты, контролируемые объектом BoxLayout сверху вниз, должны иметь одинаковое выравнивание X. Аналогично, все компоненты, контролируемые Boxlayout слева направо, как правило, должны иметь такое же выравнивание по оси Y. "

5 голосов
/ 18 апреля 2011

Иногда вам нужно проявить немного креативности и использовать вложенные панели. Но мне нравится этот подход лучше, чем пытаться выучить и запомнить все ограничения, необходимые при использовании других менеджеров компоновки (GridBagLayout, GroupLayout) там, где они предназначены для использования IDE, которые генерируют код для вас.

import java.awt.*;
import javax.swing.*;

public class BoxLayoutVertical extends JFrame
{
    public BoxLayoutVertical()
    {
        Box box = Box.createVerticalBox();

        JButton button = new JButton("A button");
        button.setAlignmentX(Component.CENTER_ALIGNMENT);
        box.add(button);

        JProgressBar progressBar = new JProgressBar(0, 100);
        progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
        box.add(progressBar);

        JPanel panel = new JPanel( new BorderLayout() );
        JLabel label = new JLabel("A label");
        label.setAlignmentX(Component.LEFT_ALIGNMENT);
        panel.add(label);
        box.add(panel);

        add(box, BorderLayout.NORTH);
    }

    public static void main(String[] args)
    {
        BoxLayoutVertical frame = new BoxLayoutVertical();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.setSize(300, 200);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}
2 голосов
/ 18 апреля 2011

В дополнение к моему комментарию к исходному вопросу приведен фрагмент, в котором используется DesignGridLayout :

JButton button = new JButton("Button");
JProgressBar progressBar = new JProgressBar();
JLabel label = new JLabel("Label");

// The interesting stuff is in the next 4 lines
DesignGridLayout layout = new DesignGridLayout(getContentPane());
layout.row().center().add(button).withOwnRowWidth();
layout.row().center().fill().add(progressBar);
layout.row().left().add(label);

pack();

Он делает именно то, что вы описали в своем вопросе, и не требует каких-либоспецифический вызов любого из компонентов.

1 голос
/ 18 апреля 2011

Не используйте BoxLayout.Это работает только для очень простых случаев.

Для вашего случая я бы порекомендовал либо GridBagLayout, либо (мой любимый) GroupLayout.


Для GroupLayout я создал подкласс (LayoutHelper ) с некоторыми служебными методами и полезными конструкторами, что значительно облегчает написание макета.

Конечно, обычно я выравниваю все компоненты в группе одинаково, поэтому в * это не так уж мало.1010 * ваш случай , как это было бы в простом случае.

    LayoutHelper h = new LayoutHelper(pane);

    h.setVerticalGroup
        ( h.sequential( button, progressBar, label));

    h.setHorizontalGroup
        ( ((ParallelGroup)h.parallel())
          .addComponent(button, Alignment.CENTER)
          .addComponent(progressBar)
          .addComponent(label, Alignment.TRAILING));

Вот скриншот:

screenshot

Для простого "всеговыровнены так же ", горизонтальная группа будет выглядеть так:

    h.setHorizontalGroup
        ( h.parallel (button, progressBar, label));

(необязательно с первым аргументом, указывающим выравнивание).

1 голос
/ 18 апреля 2011

Возможно, ваш код - просто фрагмент, но мне не хватает звонка на pack().

Кодирование разметки вручную может быть очень неприятно со стандартными менеджерами раскладок.Я использую MiG Layout для этой цели.Это просто, и у вас есть хороший макет всего с несколькими строками кода.Если вы не обязаны использовать BoxLayout, я бы посоветовал вам попробовать.

...