2012-06-03 3 views
8

Большинство менеджеров компоновки имеют конструкторы без аргументов (то есть вы можете создать FlowLayout с new FlowLayout(), GridLayout с new GridLayout(), GridBagLayout с new GridBagLayout() и т. Д.). Однако BoxLayout требует, чтобы вы передали как контейнер, который он будет управлять, так и ось, по которой должны быть выложены компоненты.Зачем вам нужно вызывать setLayout с BoxLayout?

Мой вопрос: так как вы уже говорит менеджер компоновки, который компонент выложить, почему вам нужно написать

BoxLayout bl = new BoxLayout(myPanel, BoxLayout.Y_AXIS); 
myPanel.setLayout(bl); 

, а не только в первой строке?

Я быстро посмотрел на the BoxLayout source code и увидел, что используемый мной конструктор (строки 178-185) не звонит target.setLayout(this) или что-то в этом роде. Похоже, было бы просто просто добавить это. Есть ли причина, почему он не включен в библиотеку Swing?

Если это имеет значение, я использую

Java версии 1.7.0

Java (TM) SE Runtime Environment (сборка 1.7.0-b147)

на Win7Pro ,

Спасибо!


SSCCE:

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JButton; 

public class BoxLayoutSSCCE extends JFrame { 

    // Change this to see what I mean 
    public static final boolean CALL_SET_LAYOUT = true; 

    public BoxLayoutSSCCE() { 
     super("Box Layout SSCCE"); 
     JPanel panel = new JPanel(); 
     BoxLayout bl = new BoxLayout(panel, BoxLayout.Y_AXIS); 
     if (CALL_SET_LAYOUT) { 
      panel.setLayout(bl); 
     } 
     panel.add(new JButton("Button 1")); 
     panel.add(new JButton("Button 2")); 
    } 

    public static void main (String[] args) { 
     BoxLayoutSSCCE blsscce = new BoxLayoutSSCCE(); 
     blsscce.pack(); 
     blsscce.setVisible(true); 
    } 
} 
+1

+1 для [sscce] (http://sscce.org/) – trashgod

ответ

5

Container должен существовать до его передачи в BoxLayout. Как правило, один пишет что-то вроде этого:

JPanel myPanel = new JPanel(); 
BoxLayout bl = new BoxLayout(myPanel, BoxLayout.Y_AXIS); 
myPanel.setLayout(bl); 

Заманчиво объединить две последние строки, но принцип наименьшего удивления предполагает, что конструктор компоновщика не иначе изменять состояние контейнера.

Удовлетворительно, javax.swing.Box предлагает «Легкий контейнер, в качестве менеджера макета которого используется объект BoxLayout."

public class Box extends JComponent implements ... { 

    public Box(int axis) { 
     super(); 
     super.setLayout(new BoxLayout(this, axis)); 
    } 
} 

Теперь одна линия будет делать:

Box myBox = new Box(BoxLayout.Y_AXIS); 
+0

Существует связанный пример [здесь] (http://stackoverflow.com/a/6076340/230513). – trashgod

+1

Это имеет смысл, и спасибо, что рассказали мне о Box. – wchargin

+0

Добро пожаловать; для справки, дизайн согласуется с обсуждаемым принципом [здесь] (http://stackoverflow.com/a/3404369/230513). – trashgod

4

BoxLayout убеждается, что методы компоновки применяются для правильного контейнера. Это принуждает, что тот же контейнер, который был указан в конструкторе используется в различных методах, такие, как layoutContainer(Container target), preferredLayoutSize(Container target) и т.д. Она сводится к checkContainer() методу, который делает проверку:

void checkContainer(Container target) { 
    if (this.target != target) { 
     throw new AWTError("BoxLayout can't be shared"); 
    } 
} 

BoxLayout реализация, вероятно, некоторые кэширует подробно о контейнере и пытается сохранить состояние, поэтому его нельзя использовать.

EDIT:

BoxLayout реализует LayoutManager2.invalidateLayout(), где он сбрасывается его детали кэшированные. Другие реализации макета следуют одному и тому же шаблону. Например, GroupLayout и OverlayLayout также требуют аргументов контейнера в своих конструкторах.

+0

Я понимаю, что это не может быть общим, однако.. , поскольку он не может быть разделен, кажется логичным, что компонент должен будет установить его как свой макет - * why * не 'BoxLayout' просто вызывает' setLayout (container) 'в конструкторе? Кроме того, почему не управляют ли другие менеджеры? – wchargin

+0

@WChargin Аргумент, указанный в конструкторе, используется BoxLayout для проверки и применения ограничения. Также см. мое редактирование о других менеджерах. – tenorsax

+0

JComponents реализует setLa yout, может быть интересно ... – mKorbel

 Смежные вопросы

  • Нет связанных вопросов^_^