John Jiang

          a cup of Java, cheers!
          https://github.com/johnshajiang/blog

             :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理 ::
            131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
          Custom Layout Manager: PyramidLayout
              已有太多關(guān)于自定義部局管理器的文章了。本文僅是一篇學(xué)習(xí)筆記,描述了如何實現(xiàn)一種像堆金字塔似的部局管理器,很簡單,也有點兒意思,可能你也會感興趣的。(2012.07.17最后更新)   

              I have developed Swing application for several years, although I'm not professional GUI developer, I'm shamed of never creating any custom layout manager. Maybe the existing Swing layout managers are too powerful to create new ones. At least, GridBagLayout is powerful enough for my real works. And we have much more flexible GroupLayout and SpringLayout, of course, both of them are too complex, in fact I never use them directly. However I indirectly take advantage of GroupLayout due to using NetBeans' GUI designer Matisse.

          1. Layout Manager basics
              Let's start with some layout manager foundation. Before this time I learn to customize layout, I always think layout manager is very mysterious. Layout is like a magic player that put a variety of components to right positions in containers. I haven't browsed any code of any layout, event the simplest one. That's why I think layout is mystery. But it's simple for me now.
              Generally, all of layout implements one or both of LayoutManager and LayoutManager2 interfaces. LayoutManager2 is LayoutManager's sub-interface, then if someone implements LayoutManager2 that means it really implements LayoutManager. Mostly all modern layouts implements LayoutManager2.
              Interface LayoutManager defines the basic methods must be implemented by every layout, all of them are intuitional: add new component--addLayoutComponent(); remove component--removeLayoutComponent(); calculate preferred size--preferredLayoutSize(); calculate minimum size--minimumLayoutSize(); how to layout the components--layoutContainer(). Absolutely, the layoutContainer() method is essential, you must instruct the parent container how to allocate space(bounds) for every component.
              The extension interface LayoutManager2 introduces more methods that if you have to: support constraints--addLayoutComponent(Component, Object); specify maximum size--maximumLayoutSize(); specify alignment--getLayoutAlignmentX() and getLayoutAlignmentY(); destroy specific caches or reset some variables when invaliding container--invalidateLayout().

          2. PyramidLayout
              Now let's feature a simple and funny layout manager--PyramidLayout. The layout allows container to add components like building a Pyramid, as shown as the image below,

              As the above, PyramidLayout puts the first component on the bottom, then puts the second on top of the first, but its bounds is smaller, ... It looks like a Pyramid, doesn't it? Here is the full codes,
          public class PyramidLayout implements LayoutManager2 {

              
          private List<Component> comps = new LinkedList<Component>();

              
          public void addLayoutComponent(final Component comp,
                      
          final Object constraints) {
                  
          synchronized (comp.getTreeLock()) {
                      comps.add(comp);
                  }
              }

              
          public void addLayoutComponent(final String name, final Component comp) {
                  addLayoutComponent(comp, null);
              }

              
          public void removeLayoutComponent(final Component comp) {
                  
          synchronized (comp.getTreeLock()) {
                      comps.remove(comp);
                  }
              }

              
          public float getLayoutAlignmentX(final Container target) {
                  
          return 0.5F;
              }

              
          public float getLayoutAlignmentY(final Container target) {
                  
          return 0.5F;
              }

              
          public void invalidateLayout(final Container target) {
                  System.out.println();
              }

              
          public Dimension preferredLayoutSize(final Container parent) {
                  
          synchronized (parent.getTreeLock()) {
                      Insets insets = parent.getInsets();
                      
          int width = insets.left + insets.right;
                      
          int height = insets.top + insets.bottom;
                      
          if (comps.size() == 0) {
                          
          return new Dimension(width, height);
                      }

                      Dimension size = comps.get(0).getPreferredSize();
                      width += size.width;
                      height += size.height;

                      
          return new Dimension(width, height);
                  }
              }

              
          public Dimension minimumLayoutSize(final Container parent) {
                  
          synchronized (parent.getTreeLock()) {
                      Insets insets = parent.getInsets();
                      
          int width = insets.left + insets.right;
                      
          int height = insets.top + insets.bottom;
                      
          if (comps.size() == 0) {
                          
          return new Dimension(width, height);
                      }

                      Dimension size = comps.get(0).getMinimumSize();
                      width += size.width;
                      height += size.height;

                      
          return new Dimension(width, height);
                  }
              }

              
          public Dimension maximumLayoutSize(final Container target) {
                  
          return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
              }

              
          public void layoutContainer(final Container parent) {
                  
          synchronized (parent.getTreeLock()) {
                      Dimension parentSize = parent.getSize();
                      
          int compsCount = comps.size();
                      Dimension step = new Dimension(parentSize.width / (2 * compsCount),
                              parentSize.height / (2 * compsCount));

                      
          for (int i = 0; i < compsCount; i++) {
                          Component comp = comps.get(i);
                          comp.setBounds(calcBounds(parentSize, step, i));
                          parent.setComponentZOrder(comp, compsCount - i - 1);
                      }
                  }
              }

             
          private Rectangle calcBounds(Dimension parentSize, Dimension step, int index) {
                  
          int x = step.width * index;
                  
          int y = step.height * index;
                  
          int width = parentSize.width - step.width * 2 * index;
                  
          int height = parentSize.height - step.height * 2 * index;
                  
          return new Rectangle(x, y, width, height);
              }
          }
              Collection instance "comps" manages all of components, in this case, I take a LinkedList object to add and remove UI components. The layout doesn't concern any constraint, so the two addLayoutComponent() methods have the same actions. Please see the codes for details.
              As aforementioned, layoutContainer() method really takes charge of layouting the components. The key work is allocating space for each component, namely, specifying the bounds. Calculating bounds values just applies the simplest arithmetic operations.
              According to the intention, the bottom component fills the whole parent container, so it determines the preferred and the minimum sizes. For details, please take a look at methods preferredLayoutSize() and minimumLayoutSize(). Since the layout manager doesn't take care of the maximum size, the maximumLayoutSize() method simply returns a constant value.
          posted on 2012-07-15 22:14 John Jiang 閱讀(1122) 評論(3)  編輯  收藏 所屬分類: EnglishJavaSEJavaSwingGUI

          評論

          # re: Custom Layout Manager: PyramidLayout 2012-07-15 22:16 Sha Jiang
          第一次寫英文文章,字數(shù)不多,以后還會多練習(xí)^_^  回復(fù)  更多評論
            

          # re: Custom Layout Manager: PyramidLayout 2012-07-16 08:50 chenth
          @Sha Jiang
          英語大有長進啊  回復(fù)  更多評論
            

          # re: Custom Layout Manager: PyramidLayout 2012-07-16 09:52 Sha Jiang
          @chenth
          閱讀、寫作倒在其次,最令我興奮的是,聽力有了實質(zhì)性的提高:D 不過,離流利的聽、說還有不小的差距,以后路還很長...  回復(fù)  更多評論
            

          主站蜘蛛池模板: 洛宁县| 枞阳县| 公主岭市| 英吉沙县| 侯马市| 晴隆县| 上思县| 曲靖市| 盐城市| 比如县| 武乡县| 株洲县| 普兰县| 德江县| 岑巩县| 龙里县| 昂仁县| 昭平县| 会昌县| 广饶县| 白城市| 丰台区| 岗巴县| 毕节市| 磐安县| 河西区| 永胜县| 齐齐哈尔市| 勃利县| 什邡市| 上栗县| 若尔盖县| 尉氏县| 汾西县| 邵阳市| 延长县| 成安县| 讷河市| 陆川县| 定安县| 泾川县|