SpringLayout проблема / вызов - PullRequest
0 голосов
/ 02 декабря 2009

SpringLayout считается очень мощным. Я попытался реализовать то, что я думал, было довольно простым макетом, используя SpringLayout, и я потерпел неудачу.

Уменьшено до минимума, я хочу 4 кнопки J на ​​моем кадре, рядом:

*=====================*
| +--+ +--+ +--+ +--+ |
| |b1| |b2| |b3| |b4| |
| +--+ +--+ +--+ +--+ |
*=====================*

Я хочу, чтобы все 4 имели одинаковый размер независимо от текста.

Я хочу, чтобы самые внешние (b1 и b4) имели постоянное горизонтальное расстояние 5 пикселей от границ контейнера и 5 пикселей границы к северу и югу от кнопок, которые имеют одинаковую высоту.

Я хочу, чтобы промежутки между кнопками также составляли 5 пикселей.

Пока все просто. У меня есть больше ограничений:

  • Когда рамка становится шире (пользователь / мышь), я хочу, чтобы промежутки между кнопками (b1 / b2, b2 / b3, b3 / b4) расширялись, а не кнопки.

  • Если рамка становится меньше, я хочу, чтобы промежутки между кнопками сократились до 1 или, возможно, до 0, прежде чем другие вещи уступят место.

  • Я ожидаю, что pack() на рамке даст мне окно правильного размера для кнопок с пропусками по умолчанию в 5 пикселей и рамкой вокруг них в 5 пикселей.

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

Теперь, когда у меня есть пользовательские кнопки, которые заботятся о равномерном определении размера, я мог бы довольно легко удовлетворить эти требования с помощью GridBagLayout и, возможно, еще проще с MigLayout. Это не тот ответ, который я ищу. В частности, мой вопрос:

Можно ли сделать так, чтобы этот макет работал правильно с помощью SpringLayout? Как?

В макете даже игнорируются мои кнопки getMaximumSize(). Я делаю что-то не так или SpringLayout прослушивается?

Большое спасибо.

public class SpringLayoutTest extends JFrame {

public SpringLayoutTest() {
  setLocation(100,100);
  setSize(400, 300);
  Container cp = getContentPane();
  SpringLayout layout = new SpringLayout();
  cp.setLayout(layout);

  SiblingButton b1, b2, b3, b4;
  cp.add(b1 = new SiblingButton("..."));
  cp.add(b2 = new SiblingButton("iii"));
  cp.add(b3 = new SiblingButton("xxx"));
  cp.add(b4 = new SiblingButton("WWW"));

  layout.putConstraint(NORTH, b1, 5, NORTH, cp);
  layout.putConstraint(SOUTH, b1, Spring.minus(Spring.constant(5)), SOUTH, cp);
  layout.putConstraint(NORTH, b2, 5, NORTH, cp);
  layout.putConstraint(SOUTH, b2, Spring.minus(Spring.constant(5)), SOUTH, cp);
  layout.putConstraint(NORTH, b3, 5, NORTH, cp);
  layout.putConstraint(SOUTH, b3, Spring.minus(Spring.constant(5)), SOUTH, cp);
  layout.putConstraint(NORTH, b4, 5, NORTH, cp);
  layout.putConstraint(SOUTH, b4, Spring.minus(Spring.constant(5)), SOUTH, cp);

  layout.putConstraint(WEST, b1, 5, WEST, cp);
  layout.putConstraint(WEST, b2, Spring.constant(1, 5, Integer.MAX_VALUE), EAST, b1);
  layout.putConstraint(WEST, b3, Spring.constant(1, 5, Integer.MAX_VALUE), EAST, b2);
  layout.putConstraint(WEST, b4, Spring.constant(1, 5, Integer.MAX_VALUE), EAST, b3);

  layout.putConstraint(EAST, b4, Spring.minus(Spring.constant(5)), EAST, cp);

  layout.putConstraint(WEST, cp, Spring.minus(Spring.constant(5)), WEST, b1);
}

public static void main(String[] args) {
  (new SpringLayoutTest()).setVisible(true);
}

SiblingButton - довольно бесхитростная реализация. Пожалуйста, не обращайте внимания на недостатки дизайна, это только для демонстрационных целей.

class SiblingButton extends JButton {

static ArrayList<SiblingButton> siblings = new ArrayList<SiblingButton>();

public SiblingButton(String text) {
  super(text);
  siblings.add(this);
}

public Dimension getMaximumSize() {
  return getPreferredSize();
}

public Dimension getMinimumSize() {
   return getPreferredSize();
}

public Dimension getPreferredSize() {
  Dimension mx = new Dimension(0, 0);
  for (SiblingButton sb : siblings) {
     mx = new Dimension(Math.max(mx.width, sb.originalPreferredSize().width), 
           Math.max(mx.height, sb.originalPreferredSize().height));
  }
  return mx;
}

Dimension originalPreferredSize() {
  return super.getPreferredSize();
}

}

ОБНОВЛЕНИЕ / Заключение

Прошло уже 24 часа, и ответ был подавляющим. Одинокий ответ (спасибо, Camickr!) Даже не пытается коснуться SpringLayout. Я не думаю, что это плохо отражается не на SO-сообществе, а на полезности SpringLayout!

У меня сложилось впечатление, что SpringLayout - рыжий пасынок менеджеров по макету, полезный в некоторых отношениях, но настолько мало используемый, что никто не имеет опыта работы с ним, и никто не потрудился сообщить об ошибках Sun.

Для меня оказалось, что GroupLayout делает все, что мне нужно, и позволил мне выполнить то, что я хотел, именно с разумным количеством кода. Приветственное изменение от GridBagLayout, шаги, которые мне нужно было предпринять для достижения намеченного макета, были понятны мне с самого начала, и мне просто нужно было сесть и написать код.

Для всех, кого это волнует, вот характеристики GroupLayout, которые сделали его настолько полезным для меня:

  • Компоновка выполняется более или менее отдельно для горизонтального и вертикального направлений. Много гибкости и более простой код;
  • Можно вкладывать сетки без необходимости вводить контейнеры только для хранения макета;
  • Возможно вставить пробелы с указанными ограничениями;
  • Возможно сформировать произвольные группы компонентов с общими спецификациями размеров, т. Е. Все компоненты имеют те же размеры, что и самые большие в группе; и
  • Можно изменить размер компонента (например, MaximumSize = предпочитаемый размер) без необходимости подкласса компонента.

Ответы [ 2 ]

1 голос
/ 02 декабря 2009

Вы можете использовать BoxLayout:

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

public class BoxExample extends JFrame
{
    public BoxExample()
    {
        Box box = Box.createHorizontalBox();
        box.setBorder( new EmptyBorder(5, 5, 5, 5) );
        Dimension size = new Dimension(100, 25);

        box.add( createButton("Button1", size) );
        box.add( createStrut() );
        box.add( createButton("Button2", size) );
        box.add( createStrut() );
        box.add( createButton("Button3", size) );
        box.add( createStrut() );
        box.add( createButton("Button4", size) );

        add( box );
    }

    private JButton createButton(String text, Dimension size)
    {
        JButton button = new JButton(text);
        button.setPreferredSize( size );
        button.setMinimumSize( size );
        button.setMaximumSize( size );
        return button;
    }

    private Component createStrut()
    {
        JComponent component = (JComponent)Box.createHorizontalStrut(5);
        component.setMinimumSize(new Dimension(0, 0));
        component.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
        return component;
    }

    public static void main(String[] args)
    {
        BoxExample frame = new BoxExample();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}
0 голосов
/ 01 апреля 2010

Вам необходимо установить ограничение контейнера (панель содержимого фрейма) и, более точно, ограничение к востоку и югу от него. Прочитайте учебник по этому вопросу:
http://java.sun.com/docs/books/tutorial/uiswing/layout/spring.html
SpringDemo3 объясняет все это

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...