线性布局管理器

线性布局管理器,在后续swing设计中经常要用到,非常常见。

这是我根据阿发老师的讲课内容,自己学习运用的,不足之处,多多谅解。

线性布局方式,分为 水平布局 和 竖直布局 

(1)、水平布局。各个子控件在水平方向上依次排列,每个控件的宽度可以单独指定, 可以使用MyXLayout

例如:

setLayout(new AfXLayout(5)); // 子控件之间的间距为5像素 

add(a1, "80px");   -"80px" 固定占80像素 (不会随窗体的变化而变化)

add(a2, "0%");  -"20%"  固定占总空间的20% 

add(a3, "auto");   -"auto"  采用控件的Preferred Size (根据内容的尺寸确定)

add(a4, "1w");    -"1w"   按权重分配剩余空间 

权重问题;

例如,一个控件为"2w",一个控件为"3w",则它们将按2:3比例瓜分剩余的空间。

2、测试

public class Test13 extends JFrame {
    //线性布局之水平布局
    JPanel jp=new JPanel();//容器
    JLabel j1=new ColorfulLabel3("hello",Color.GREEN);
    JLabel j2=new ColorfulLabel3("hello",Color.RED);
    JLabel j3=new ColorfulLabel3("hello",Color.GRAY);
    JLabel j4=new ColorfulLabel3("hello",Color.BLUE);
    public Test13(String title) {
        super(title);
        setLayout(new BorderLayout());
        setSize(400, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jp.setLayout(new MyXLayoutMan(5));
        add(jp,BorderLayout.CENTER);
        //设置标签不透明
        j1.setOpaque(true);
        jp.add(j1, "80px");
        j2.setOpaque(true);
        jp.add(j2, "20%");
        j3.setOpaque(true);
        jp.add(j3, "auto");
        j4.setOpaque(true);
        jp.add(j4, "1w");
        setVisible(true);
    }


    public static void main(String[] args) {
        new Test13("水平布局测试");
    }


}
class ColorfulLabel3 extends JLabel {
    private String title;
    private Color color;


    public ColorfulLabel3(String title, Color color) {
        super();


        setText(title);
        setOpaque(true);
        setBackground(color);


    }


    @Override
    public String toString() {
        return "ColorfulLabel{" +
                "title='" + title + '\'' +
                ", color=" + color +
                '}';
    }
}

测试结果:

 

 

 

 

2、附上阿发老师(有修改)源码内容

(1)水平布局器

public class MyXLayoutMan implements LayoutManager2
{
    private List<Item> items = new ArrayList<>();
    private int gap = 2;
    private boolean usePerferredSize = false; // 竖立方向是否占满

    public MyXLayoutMan()
    {
    }
    public MyXLayoutMan(int gap)
    {
        this.gap = gap; // 控件之间的间距
    }
    public MyXLayoutMan(int gap, boolean usePerferredSize)
    {
        this.gap = gap;
        this.usePerferredSize = usePerferredSize;
    }

    @Override
    public void addLayoutComponent(String name, Component comp)
    {
        Item item = new Item();
        item.comp = comp;
        item.constraints = "auto";
        items.add(item);
    }

    @Override
    public void removeLayoutComponent(Component comp)
    {
        Iterator<Item> iter = items.iterator();
        while(iter.hasNext())
        {
            Item item = iter.next();
            if(item.comp == comp)
            {
                iter.remove();
            }
        }
    }

    @Override
    public void addLayoutComponent(Component comp, Object constraints)
    {
        Item item = new Item();
        item.comp = comp;
        item.constraints = (String) constraints;
        items.add(item);
    }

    @Override
    public Dimension preferredLayoutSize(Container parent)
    {
        return new Dimension(30,30);
    }

    @Override
    public Dimension minimumLayoutSize(Container parent)
    {
        return new Dimension(30,30);
    }

    @Override
    public Dimension maximumLayoutSize(Container target)
    {
        return new Dimension(30,30);
    }


    @Override
    public void layoutContainer(Container parent)
    {
        // 得到内矩形
        Rectangle rect = new Rectangle(parent.getWidth(), parent.getHeight());
        //Rectangle rect = parent.getBounds();
        Insets insets = parent.getInsets();
        rect.x += insets.left;
        rect.y += insets.top;
        rect.width -= (insets.left + insets.right);
        rect.height -= (insets.top + insets.bottom);

        // 第一轮:过滤到无效的 Item ( 有些控件是隐藏的 )
        List<Item> validItems = new ArrayList<>();
        for(Item it: items )
        {
            if(it.comp.isVisible())
                validItems.add(it);
        }

        // 第二轮处理:百分比,像素,auto的,直接计算出结果; 权重的,在第三轮计算
        int totalGapSize = gap * (validItems.size() - 1);// 间距大小
        int validSize = rect.width - totalGapSize;
        int totalSize = 0;
        int totalWeight = 0;
        for(Item it : validItems)
        {
            Dimension preferred = it.comp.getPreferredSize();
            it.width = preferred.width;
            it.height = usePerferredSize ? preferred.height : rect.height;
            it.weight = 0;

            // 计算宽度
            String cstr = it.constraints;
            if( cstr == null || cstr.length() == 0)
            {
                //System.out.println("(AfRowLayout) Warn: Must define constraints when added to container!");
            }
            else if( cstr.equals("auto"))
            {
            }
            else if(cstr.endsWith("%")) // 按百分比
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-1));
                it.width = validSize * num / 100;
            }
            else if(cstr.endsWith("w")) // 按权重
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-1));
                it.width = 0;
                it.weight = num;
            }
            else if(cstr.endsWith("px")) // 按权重
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-2));
                it.width = num;
            }
            else // 按像素
            {
                int num = Integer.valueOf(cstr);
                it.width = num;
            }

            totalSize += it.width;
            totalWeight += it.weight;

            //System.out.println("计算值:width=" + it.width + ",weight=" + it.weight);
        }

        // 第三轮: 剩余空间按权重分配
        if( totalWeight > 0)
        {
            int remainSize = validSize - totalSize;
            double unit = (double) remainSize / totalWeight;
            for(Item it : validItems)
            {
                if(it.weight > 0)
                {
                    it.width = (int)( unit * it.weight );
                }
            }
        }

        //System.out.println("总宽度: " + rect.width);

        // 第四轮: 按宽度和高度布局
        int x = 0;
        for(Item it : validItems)
        {
            int y = (rect.height - it.height)/2;
            if(x + it.width > rect.width)
                it.width = rect.width - x;
            if(it.width <= 0) break;

            it.comp.setBounds(rect.x + x, rect.y + y, it.width, it.height);

            //System.out.println("宽度: " + it.width);
            x += it.width;
            x += gap; // 间距
        }
    }

    @Override
    public float getLayoutAlignmentX(Container target)
    {
        return 0;
    }

    @Override
    public float getLayoutAlignmentY(Container target)
    {
        return 0;
    }

    @Override
    public void invalidateLayout(Container target)
    {

    }

    //内部类
    private static class Item
    {
        Component comp;
        String constraints = "auto";
        int width = 0;
        int height = 0;
        int weight = 0;  // 权重
    }


}

(2)垂直布局管理器

public class MyYLayoutMan implements LayoutManager2
{
    private List<Item> items = new ArrayList<>();
    private int gap = 2;
    private boolean usePerferredSize = false; // 竖立方向是否占满

    public MyYLayoutMan()
    {
    }
    public MyYLayoutMan(int gap)
    {
        this.gap = gap; // 控件之间的间距
    }
    public MyYLayoutMan(int gap, boolean usePerferredSize)
    {
        this.gap = gap;
        this.usePerferredSize = usePerferredSize;
    }

    @Override
    public void addLayoutComponent(String name, Component comp)
    {
        Item item = new Item();
        item.comp = comp;
        item.constraints = "auto";
        items.add(item);
    }

    @Override
    public void removeLayoutComponent(Component comp)
    {
        Iterator<Item> iter = items.iterator();
        while(iter.hasNext())
        {
            Item item = iter.next();
            if(item.comp == comp)
            {
                iter.remove();
            }
        }
    }

    @Override
    public void addLayoutComponent(Component comp, Object constraints)
    {
        Item item = new Item();
        item.comp = comp;
        item.constraints = (String) constraints;
        items.add(item);
    }

    @Override
    public Dimension preferredLayoutSize(Container parent)
    {
        return new Dimension(30,30);
    }

    @Override
    public Dimension minimumLayoutSize(Container parent)
    {
        return new Dimension(30,30);
    }

    @Override
    public Dimension maximumLayoutSize(Container target)
    {
        return new Dimension(30,30);
    }


    @Override
    public void layoutContainer(Container parent)
    {
        // 得到内矩形
        Rectangle rect = new Rectangle(parent.getWidth(), parent.getHeight());
        //Rectangle rect = parent.getBounds();
        Insets insets = parent.getInsets();
        rect.x += insets.left;
        rect.y += insets.top;
        rect.width -= (insets.left + insets.right);
        rect.height -= (insets.top + insets.bottom);

        // 第一轮:过滤到无效的 Item ( 有些控件是隐藏的 )
        List<Item> validItems = new ArrayList<>();
        for(Item it: items )
        {
            if(it.comp.isVisible())
                validItems.add(it);
        }

        // 第二轮处理:百分比,像素,auto的,直接计算出结果; 权重的,在第三轮计算
        int totalGapSize = gap * (validItems.size() - 1);// 间距大小
        int validSize = rect.height - totalGapSize;
        int totalSize = 0;
        int totalWeight = 0;
        for(Item it : validItems)
        {
            Dimension preferred = it.comp.getPreferredSize();
            it.width = usePerferredSize ? preferred.width : rect.width;
            it.height = preferred.height;
            it.weight = 0;

            // 计算宽度
            String cstr = it.constraints;
            if( cstr == null || cstr.length() == 0)
            {
                //System.out.println("(AfColumnLayout) Warn: Must define constraints when added to container!");
            }
            else if( cstr.equals("auto"))
            {
            }
            else if(cstr.endsWith("%")) // 按百分比
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-1));
                it.height = validSize * num / 100;
            }
            else if(cstr.endsWith("w")) // 按权重
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-1));
                it.height = 0;
                it.weight = num;
            }
            else if(cstr.endsWith("px")) // 按权重
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-2));
                it.height = num;
            }
            else // 按像素
            {
                int num = Integer.valueOf(cstr);
                it.height = num;
            }

            totalSize += it.height;
            totalWeight += it.weight;

            //System.out.println("计算值:width=" + it.width + ",weight=" + it.weight);
        }

        // 第三轮: 剩余空间按权重分配
        if( totalWeight > 0)
        {
            int remainSize = validSize - totalSize;
            double unit = (double) remainSize / totalWeight;
            for(Item it : validItems)
            {
                if(it.weight > 0)
                {
                    it.height = (int)( unit * it.weight );
                }
            }
        }

        //System.out.println("总宽度: " + rect.width);

        // 第四轮: 按宽度和高度布局
        int y = 0;
        for(Item it : validItems)
        {
            int x = 0; // 水平靠左
            if(y + it.height > rect.height)
                it.height = rect.height - y;
            if(it.height <= 0) break;

            it.comp.setBounds(rect.x + x, rect.y + y, it.width, it.height);

            //System.out.println("宽度: " + it.width);
            y += it.height;
            y += gap; // 间距
        }
    }

    @Override
    public float getLayoutAlignmentX(Container target)
    {
        return 0;
    }

    @Override
    public float getLayoutAlignmentY(Container target)
    {
        return 0;
    }

    @Override
    public void invalidateLayout(Container target)
    {

    }

    //内部类   private static class Item
    {
        Component comp;
        String constraints = "auto";
        int width = 0;
        int height = 0;
        int weight = 0;  // 权重
    }


}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霓乤

谢谢支持,菜鸟会继续努力..

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值