JAVA桌面UI編程之佈局管理器

佈局管理器

爲了跨平臺java引入了佈局管理器來管理界面,JAVA一共有6種佈局管理器,下面是介紹

BorderLayout

界面分東西南北中5個方向,最多隻能顯示5個控件,默認放入中間,下面的程序將panel和panel2放在了中間和南邊。放在中間的空間大小默認有內容大小爲剩餘的部分,不可設置。就如下面的程序,不能設置panel2的大小
this.getContentPane().add(panel,BorderLayout.SOUTH);
this.getContentPane().add(panel2,BorderLayout.CENTER);

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;

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

public class BorderFrame extends JFrame{
    JButton btOK = new JButton("OK");
    JButton btNO = new JButton("NO");

    JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    JPanel panel2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
    public BorderFrame(){
        this.getContentPane().add(panel,BorderLayout.SOUTH);
        this.getContentPane().add(panel2,BorderLayout.CENTER);
        panel2.setBackground(Color.black);
        panel2.setSize(100,200);
        this.setBackground(Color.red);
        panel.add(btOK);
        panel.add(btNO);
        panel.setBackground(Color.blue);
        this.setSize(300,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BorderFrame frame = new BorderFrame();

    }

}

這裏寫圖片描述

FlowLayout

看作行集,行高不能用setSize設置,由內容決定,可以設置左中右居,還有。就如上面的程序,panel不能設置大小,panel2也不能,之所有有這麼大是因爲發在了BorderLayout有東西填充。若將panel2放在上邊,效果如下
this.getContentPane().add(panel2,BorderLayout.NORTH);
這裏寫圖片描述
放在左邊效果有如下 :
this.getContentPane().add(panel2,BorderLayout.WEST);
這裏寫圖片描述

GridLayout

網格管理器,把容器的顯示位置化格子,然後把控件放到等寬等高的格子,

GridLayout layout = new GridLayout(行數,列數);
//  當行數爲0時,增加控件時會保持一個列的情況下隨控件增長;列數爲0時亦是如此。但不能同時爲0

一個對話框例子

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import java.awt.event.*;

public class LoginDialogDemo extends JFrame {
    JButton button = new JButton("Click Me");
    JPanel panel = new JPanel(new FlowLayout());

    public LoginDialogDemo(){
        final JFrame frame = this;
        // BorderLayout管理器
        this.getContentPane().add(panel, BorderLayout.SOUTH);
        panel.add(button);

        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                showLoginDialog(frame);
            }
        });

        this.setSize(400,200);
        this.setTitle("顯示登陸對話框");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    void showLoginDialog(JFrame frame){
        // gridLayout自增
        JPanel p = new JPanel(new GridLayout(0,1));
        JTextField tfUserName = new JTextField();
        JPasswordField tfPassword = new JPasswordField();
        p.add(new JLabel("Username:"));
        p.add(tfUserName);
        p.add(new JLabel("Password:"));
        p.add(tfPassword);
        if(JOptionPane.showConfirmDialog(frame,
                                        p,
                                        "Login",
                                        JOptionPane.OK_CANCEL_OPTION,
                                        JOptionPane.PLAIN_MESSAGE)==
                                        JOptionPane.OK_OPTION){
            System.out.println("User Name:"+tfUserName.getText());
            System.out.println("Password:"+new String(tfPassword.getName()));
        }

    }

    public static void main(String[] args){
        LoginDialogDemo frame = new LoginDialogDemo();
    }
}

這裏寫圖片描述
這裏寫圖片描述

BoxLayout

允許控件按X/Y抽擺放。

public BoxLayout(Container target,int axis) 
// target表示當前管理的容器,若爲this則管理自己所在的容器
import java.awt.TextArea;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class BoxLayoutFrame extends JFrame{
    BoxLayoutTest panel = new BoxLayoutTest();
    public BoxLayoutFrame(){
        this.getContentPane().add(panel);
        this.setSize(500,500);
        this.setTitle("測試界面佈局");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BoxLayoutFrame frame = new BoxLayoutFrame();
    }

}

class BoxLayoutTest extends JPanel{
    BoxLayoutTest(){
        //set the layout to a X-axis BoxLayout
        setLayout(new BoxLayout(this,BoxLayout.X_AXIS));

        //Create three components
        JTextField textField = new JTextField();  //單行文本輸入框
        // JTextArea構造具有指定行數和列數的新的空 TextArea。
        TextArea textArea = new TextArea(4,20);  
        JButton button = new JButton("this is a Button");

        //add the three components to the BoxLayouts
        add(new JLabel("TextField:"));
        add(textField);
        add(new JLabel("TextArea:"));
        add(textArea);
        add(new JLabel("button:"));
        add(button);
    }
}

CardLayout

CardLayout佈局,某個界面像放動畫一樣貼換內容。比如實現一個界面內多個

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import java.awt.Panel;
import java.awt.event.*;

public class CardLayoutFrame extends JFrame {

    JButton btnPrevious = new JButton("Previous");
    JButton btnNext = new JButton("Next");

    JPanel panelFlow = new JPanel(new FlowLayout());
    JPanel panelCard = new JPanel(new CardLayout());
    int currentIndex = 0;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    CardLayoutFrame frame = new CardLayoutFrame();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public CardLayoutFrame() {
        this.getContentPane().add(panelFlow, BorderLayout.SOUTH);
        this.getContentPane().add(panelCard,BorderLayout.CENTER );
        panelCard.add(createCard(1), "Card1");
        panelCard.add(createCard(2), "Card2");
        panelFlow.add(btnPrevious);
        panelFlow.add(btnNext);

        ActionListener listener = new ActionListener(){
            public void actionPerformed(ActionEvent e){
                switchCard();
            };
        };

        btnPrevious.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                switchCard();
            };
        });
        btnNext.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                switchCard();
            };
        });

        this.setSize(300,200);
        this.setTitle("測試界面佈局");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    // 生產卡片
    JPanel createCard(int Index){
        JPanel panel = new JPanel(new BorderLayout());
        JLabel label = new JLabel("<html><h1 style = color:red>"+
        "This is Panel"+ Index+"</h1></html>");

        label.setHorizontalAlignment(JLabel.CENTER);
        panel.add(label);

        return panel;
    }

    void switchCard(){
        CardLayout c1 = (CardLayout) panelCard.getLayout();
        if(currentIndex == 0){
            currentIndex ++;
            c1.show(panelCard, "Card2");
        }else{
            currentIndex--;
            c1.show(panelCard, "Card1");
        }
    }
}

這裏寫圖片描述

GridBagLayout

每個加入容器的控件創建一個GridBagConstraints對象,下面分析這個對象的構造函數的參數

public GridBagConstraints(
    int gridx,int gridy,   //控件的位置,單位爲網格
    int gridwidth,int gridheight,  // 組件佔幾列幾行
    double weightx,double weighty,  // 水平和垂直拉伸權值
    int anchor,  // 停靠方向,默認CENTER,有NORTHEAST,EAST,SOUTHEAST,SOUTH,SOUTHWEST等
    int fill,  // 拉伸的方向,有NONE,HORIZONTAL,VERTICAL
    insets insets(上,左,下,右),  // 外部填充,填充的區域是組件與所處格子邊框之間的部分。 當組件不能填滿其格時,通過 insets來指定四周(即上下左右)所留空隙
    int ipadx,ipady  //  組件間的橫縱向間距
)

一個單例使用實例

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class GridBagLayoutFrame extends JFrame {

    JButton btnOK = new JButton("OK");
    JButton btnCancel = new JButton("Cancel");
    JPanel panelFlow = new JPanel(new FlowLayout());
    JPanel panelGrid;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    GridBagLayoutFrame frame = new GridBagLayoutFrame();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public GridBagLayoutFrame() {
        panelGrid = createPanelGridBag();
        this.getContentPane().add(panelFlow, BorderLayout.SOUTH);
        this.getContentPane().add(panelGrid,BorderLayout.CENTER);
        panelFlow.add(btnOK);
        panelFlow.add(btnCancel);

        this.setTitle("測試界面");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();   //窗口自適應組件大小
        this.setVisible(true);

    }

    JPanel createPanelGridBag(){
        JPanel panelGridBag = new JPanel(new GridBagLayout());
        JLabel label1 = new JLabel();
        JLabel label2 = new JLabel();
        JLabel label3 = new JLabel();
        JLabel label4 = new JLabel();

        JTextField textField1 = new JTextField();
        JTextField textField2 = new JTextField();
        JTextField textField3 = new JTextField();
        JTextField textField4 = new JTextField();

        label1.setText("User Name:");
        label2.setText("Telephone:");
        label3.setText("Address:");
        label4.setText("Company:");

        textField1.setText("Your Name");
        textField2.setText("88888888");
        textField3.setText("Shanghai,China");
        textField4.setText("Your company");

//      Insets(int top, int left, int bottom, int right) 
//      創建並初始化具有指定頂部、左邊、底部、右邊 inset 的新 Insets 對象。
        panelGridBag.add(label1,
                new GridBagConstraints(0,0,1,1,0.0,0.0,
                        GridBagConstraints.WEST,GridBagConstraints.NONE,
                        new Insets(45, 50, 0, 0),20,0
                        )
                );
        panelGridBag.add(label2,
                new GridBagConstraints(0,1,1,1,0.0,0.0,
                        GridBagConstraints.WEST,GridBagConstraints.NONE,
                        new Insets(34,50,0,0),20,0
                        )
                );
        panelGridBag.add(label3,
                new GridBagConstraints(0,2,1,1,0.0,0.0,
                        GridBagConstraints.WEST,GridBagConstraints.NONE,
                        new Insets(28,50,0,0),33,0
                        )
                );
        panelGridBag.add(label4,
                new GridBagConstraints(0,3,1,1,0.0,0.0,
                        GridBagConstraints.WEST,GridBagConstraints.NONE,
                        new Insets(28,50,50,0),26,0
                        )
                );


        panelGridBag.add(textField1,
                new GridBagConstraints(1,0,1,1,1.0,0.0,
                        GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,
                        new Insets(44,25,0,84),97,0
                        )
                );
        panelGridBag.add(textField2,
                new GridBagConstraints(1,1,1,1,1.0,0.0,
                        GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,
                        new Insets(31,25,0,84),97,0
                        )
                );
        panelGridBag.add(textField3,
                new GridBagConstraints(1,2,1,1,1.0,0.0,
                        GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,
                        new Insets(25,25,0,84),97,0
                        )
                );

        panelGridBag.add(textField4,
                new GridBagConstraints(1,3,1,1,1.0,0.0,
                        GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,
                        new Insets(26,25,50,84),97,0
                        )
                );

        return panelGridBag;
    }

}

這裏寫圖片描述

難點: weightx,weighty
在書上看到這兩個值設爲[0,1],然後自個好奇就隨便調了幾個值,結果UI依然不受影響,然後通過查閱才知道其實這兩個值得取值無限制,只要合理即可,每個組件的這兩個值還與其他因素有關。詳細請看論文
java的拉伸作用規則:
1. 跨多個格子且是第一列(行)則作用於最右(下)邊的格子;若非出現在第一行或列且weight爲0,則作用於最右下格子,否則按比例值(某個x或y上所有某個weight佔總weight的值)拉伸。
2. 拉伸值爲0時不一定不能拉伸,只要所在行存在拉伸對象,就能跟着拉伸。

下面給出論文中的一個源碼:

import java.awt.*;

import javax.swing.*;

public class DWPMessGrigBag extends JFrame {

    JButton Ding,Wei,Ping,Exit,Help;
    JLabel address,family;
    JPanel panel;
    JTextField textField,mousePosition;
    JList familyList,addrList;
    JTextArea textArea;

    /**
     * Create the frame.
     */
    public DWPMessGrigBag() {
        Ding = new JButton("丁");
        Wei = new JButton("衛");
        Help = new JButton("幫助");
        Ping = new JButton("平");

        family = new JLabel("丁家成員");
        address = new JLabel("地址信息");       
        String[] str = {"丁衛平","張燕","丁培桓"};
        String[] addstr = {"湖南","桃花","灰山港"};

        textField = new JTextField();
        textField.setBackground(Color.green);
        mousePosition = new JTextField();
        Exit = new JButton("退出");
        familyList = new JList(str);
        familyList.setBackground(Color.yellow);
        addrList = new JList (addstr);
        addrList.setBackground(Color.green);
        textArea = new JTextArea();
        textArea.setBackground(Color.lightGray.brighter());
        GridBagLayout layout = new GridBagLayout();
        this.setLayout(layout);
        GridBagConstraints s = new GridBagConstraints();
        s.fill = GridBagConstraints.BOTH;


        s.gridwidth = 1;
        s.weightx = 0;
        s.weighty = 0;
        layout.setConstraints(Ding,s);
        layout.setConstraints(Wei,s);
        layout.setConstraints(Ping,s);

        s.gridx = 4;
        s.gridy = 0;
        layout.setConstraints(Help, s);

        s.gridx = 0;
        s.gridy = 1;
        s.gridwidth = 2;
        layout.setConstraints(family, s);

        s.gridx = 2;
        s.gridy = 1;
        s.weightx = 13;
        layout.setConstraints(textField, s);

        s.gridx = 4;
        s.gridwidth = 1;
        s.weightx = 0;
        layout.setConstraints(Exit, s);

        s.gridx = 0;
        s.gridy = 2;
        s.gridwidth = 2;
        s.weightx = 0;
        s.weighty = 90;
        layout.setConstraints(familyList, s);

        s.gridx = 2;
        s.gridheight = 4;
        s.gridwidth = 3;
        s.weightx = 31;
        s.weighty = 44;
        layout.setConstraints(textArea,s);

        s.gridx = 0;
        s.gridy = 3;
        s.gridwidth = 2;
        s.weightx = 0;
        s.weighty = 0;
        s.gridheight = 1;
        layout.setConstraints(address, s);

        s.gridy = 4;
        s.weighty = 30;
        layout.setConstraints(addrList, s);

        s.weighty = 0;
        s.gridy = 5;
        layout.setConstraints(mousePosition, s);

        this.add(Ding);
        this.add(Wei);
        this.add(Ping);
        this.add(Help);

        this.add(family);
        this.add(textField);
        this.add(Exit);

        this.add(familyList);
        this.add(textArea);
        this.add(address);


        this.add(addrList);
        this.add(mousePosition);

        this.setSize(600,600);
        this.setVisible(true);

    }

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    DWPMessGrigBag frame = new DWPMessGrigBag();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

這裏寫圖片描述

參考:
《JAVA編程實踐指南》,邵榮,清華大學出版社
Java學習筆記之卡片式佈局CardLayout
GridBagLayout 以及 GridBagConstraints 用法
GridBagConstrains類成員weightx和weighty的使用方法研究

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章