【Java-GUI】01 AWT & 布局

https://www.bilibili.com/video/BV1Z54y1S7ns

——1、AWT

完整描述:Abstract Window Toolkit 抽象窗口工具集

提供的API资源

抽象基类:

java.awt.Component
java.awt.MenuComponent

布局接口:

java.awt.LayoutManager

容器组件:

java.awt.Container

——2、Container继承体系

// 子类窗体容器
java.awt.Window 
// 子类面板容器
java.awt.Panel 
// 子类滚动条窗格容器
java.awt.ScrollPane 

缺省的布局方式:

Window是可以独立存在的顶级窗口,默认使用BorderLayout边界布局

Panel可以嵌入其他组件,默认使用FlowLayout流式布局

ScrollPane是一个带滚动条的容器,和Window一样使用BorderLayout边界布局

常用的方法:

Component组件

// 设置组件在界面中出现的位置
void setLocation(int x, int y) 

// 设置组件的大小
void setSize(int width, int length)

// 等与上面的方法合并在一起
void setBounds(int x, int y, int width, int height)

// 设置是否可见(是否出现在界面中)
void setVisible(Boolean b)

Container子类

// 向容器中添加组件,返回添加的组件
Component add(Component comp)

// 获取指定位置上的组件 
Component getComponentAt(int x, int y)

// 返回容器内组件的数量
int getComponentCount()

// 返回容器内的所有组件
Component[] getComponents()

 

——3、三大组件

Window演示案例:

package cn.dzz;
import java.awt.*;

public class Main {
    public static void main(String[] args) {

        // 创建一个窗口对象
        Frame frame = new Frame("一个空窗口");

        // 设置出现的的位置 (像素单位)
        frame.setLocation(100, 100);

        // 设置窗口对象的大小 (像素单位)
        frame.setSize(600, 300);

        // 设置可见
        frame.setVisible(true);
    }
}

Panel演示案例:

panel必须放置于windows中

package cn.dzz;
import java.awt.*;

public class Main {
    public static void main(String[] args) {

        // 创建顶级的window对象
        Frame frame = new Frame("Panel案例");

        // 创建一个panel对象,该对象不可独立存在,需要放在window对象中
        Panel panel = new Panel();

        // 向panel对象中添加这些组件
        panel.add(new TextField("这是一段演示文本")); // 增加一个文本字段对象,理解为输入框
        panel.add(new Button("这是一个演示按钮")); // 增加一个按钮对象

        // 把面板对象放入window对象中
        frame.add(panel);

        // 同时设置边界和大小
        frame.setBounds(100,100,600,300);

        // 可见
        frame.setVisible(true);
    }
}

按钮字符乱码问题:

使用IDEA编写,文本字符默认设置的是UTF-8

但是我们的Windows操作系统默认采用GBK,而像这种通过接口调用系统组件的,

例如这个按钮对象,设置的中文字符就会出现问题。

ScrollPane案例演示:

package cn.dzz;
import java.awt.*;

public class Main {
    public static void main(String[] args) {

        // 创建顶级的window对象
        Frame frame = new Frame("ScrollPane-Demo");

        ScrollPane scrollPane = new ScrollPane();
        // 要设置始终显示滚条
        // ScrollPane scrollPane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);

        scrollPane.add(new TextField("This is a test text"));
        scrollPane.add(new Button("This is a test button"));

        frame.add(scrollPane);

        // 同时设置边界和大小
        frame.setBounds(100,100,600,300);

        // 可见
        frame.setVisible(true);
    }
}

 

——4、LayoutManager布局管理器接口

// 布局管理器接口
java.awt.LayoutManager
    |
// 栅格布局 和 流式布局
java.awt.GridLayout
java.awt.FlowLayout

// 布局管理器接口的子接口
java.awt.LayoutManager2
    |
// 卡片布局
java.awt.CardLayout
// 栅格包布局
java.awt.GridBagLayout
// 边界布局
java.awt.BorderLayout

 

——5、布局结构

1、流式布局:

指组件的排版统一向一个方向设置,直到边界,向下从头继续

构造器:

FlowLayout() 
默认构造器,默认的布局(垂直 + 水平 间距)

FlowLayout(int align)
指定对齐方式,默认垂直水平间距
// 参数使用该类的枚举值
FlowLayout.LEFT // 默认值
FlowLayout.RIGHT
FlowLayout.CENTER

FlowLayout(int align,int hgap,int vgap)
指定对齐方式和垂直水平间距

案例:

package cn.dzz;
import java.awt.*;

public class Main {
    public static void main(String[] args) {

        // 创建顶级的window对象
        Frame frame = new Frame("ScrollPane-Demo");

        // 变更布局(设置布局) P1:布局方式 P2:水平间距(horizon) P3:垂直间距 (vertical)

        // frame.setLayout(new FlowLayout(FlowLayout.LEFT,20,20)); // 左对齐
        // frame.setLayout(new FlowLayout(FlowLayout.RIGHT,20,20)); // 右对齐
        frame.setLayout(new FlowLayout(FlowLayout.CENTER,20,20)); // 中对齐

        // 添加多个按钮
        for (int i = 1; i < 101; i++) {
            frame.add(new Button("button-" + i));
        }

        // 通过pack方法让程序自己设置最佳大小
        frame.pack();

        // 可见
        frame.setVisible(true);
    }
}

2、边界布局:

java.awt.BorderLayout

东—西—南—北—中(上下左右中)

上下 进行 水平调整

左右 进行 垂直调整

中 包括水平和垂直两个调整

构造器:

BorderLayout()
BorderLayout(int hgap, int vgap)

案例:

package cn.dzz;
import java.awt.*;

public class Main {
    public static void main(String[] args) {

        // 创建顶级的window对象
        Frame frame = new Frame("ScrollPane-Demo");
        
        frame.setLayout(new BorderLayout(30,10));

        frame.add(new Button("North-Button"),BorderLayout.NORTH);
        frame.add(new Button("South-Button"),BorderLayout.SOUTH);
        frame.add(new Button("East-Button"),BorderLayout.EAST);
        frame.add(new Button("West-Button"),BorderLayout.WEST);
        frame.add(new Button("Center-Button"),BorderLayout.CENTER);
        
        // 通过pack方法让程序自己设置最佳大小
        frame.pack();
        // 可见
        frame.setVisible(true);
    }
}

效果:

随着窗体的拖动,pack方法会自适应的进行调整

区域冲突问题:

package cn.dzz;
import java.awt.*;

public class Main {
    public static void main(String[] args) {

        // 创建顶级的window对象
        Frame frame = new Frame("ScrollPane-Demo");

        frame.setLayout(new BorderLayout(30,10));

        frame.add(new Button("North-Button"),BorderLayout.NORTH);
        frame.add(new Button("South-Button"),BorderLayout.SOUTH);
        frame.add(new Button("East-Button"),BorderLayout.EAST);
        frame.add(new Button("West-Button"),BorderLayout.WEST);

        // frame.add(new Button("Center-Button"),BorderLayout.CENTER);
        // frame.add(new TextField("sample text"),BorderLayout.CENTER); // 不设置边界布局会发现,这个文本字段对象占用的是中心布局,且之前的中心按钮对象被移除了

        // 要实现多个组件共存在这个边界布局的某一块中,就需要一个面板对象来存放
        Panel panel = new Panel();
        frame.add(panel,BorderLayout.CENTER);
        // 交由面板对象来存放
        panel.add(new Button("Center-Button"));
        panel.add(new TextField("sample text"));
        
        // 如果其他区域没有插入任何组件,也就是未使用的状态,窗体将会自动将其他使用的组建将该区域自适应的填充

        // 通过pack方法让程序自己设置最佳大小
        frame.pack();
        // 可见
        frame.setVisible(true);
    }
}

3、栅格布局

java.awt.GridLayout

可以理解为将窗体划分为表格来进行布局

构造器

GridLayout(int rows,int cols)  确定总共行与列
GridLayout(int rows,int cols,int hgap, int vgap) 包括水平垂直间距 

案例:

package cn.dzz;
import java.awt.*;

public class Main {
    public static void main(String[] args) {

        // 创建顶级的window对象
        Frame frame = new Frame("ScrollPane-Demo");

        // 对顶级窗体设置边界布局
        frame.setLayout(new BorderLayout());

        // 计算的输入框放入边界布局的顶部,为了可以塞入更多的其他组件,先放Panel进去
        Panel topPanel = new Panel();

        // columns 30个字符
        topPanel.add(new TextField(30));

        // 添加放有输入框的panel
        frame.add(topPanel,BorderLayout.NORTH);

        // 创建放计算器按钮的panel
        Panel buttonPanel = new Panel();
        // 按钮需要使用栅格布局  3行5列 水平4垂直4
        buttonPanel.setLayout(new GridLayout(3,5,4,4));

        for (int i = 0; i < 10; i++) {
            buttonPanel.add(new Button("" + i));
        }
        buttonPanel.add(new Button("+"));
        buttonPanel.add(new Button("-"));
        buttonPanel.add(new Button("*"));
        buttonPanel.add(new Button("/"));
        buttonPanel.add(new Button("."));

        // 将这个面板对象放入Center位置(默认是放入Center,可以不设置)
        frame.add(buttonPanel,BorderLayout.CENTER);

        // 通过pack方法让程序自己设置最佳大小
        frame.pack();
        // 可见
        frame.setVisible(true);
    }
}

效果:

4、栅格包布局

java.awt.GridBagLayout

在栅格布局的基础上支持了格子合并的操作

 

 

5、卡片布局

java.awt.CardLayout

以时间方式管理组件,加入的组件是一叠卡片。每次只有最上面的卡片可以使用

构造器:

CardLayout() 默认的卡片管理器布局
CardLayout(int hgap,int vgap) 指定卡片与容器左右边界的间距

方法:

first(Container target) 显示target容器的第一个组件
last(Container target) 显示target容器的最后一个组件
previous(Container target) 显示target容器的上一个组件
next(Container target) 显示target容器的下一个组件
show(Container target,String name) 显示Target容器指定的名字卡片

案例:

package cn.dzz;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {
    public static void main(String[] args) {

        // 窗体
        Frame frame = new Frame();

        // 创建一个panel对象用来存放卡片对象
        Panel cardPanel = new Panel();

        // 卡片布局对象是给这个卡片面板对象设置的
        CardLayout cardLayout = new CardLayout();
        cardPanel.setLayout(cardLayout);

        // 创建一个字符串数组
        String[] strings = {
                "Card - 1",
                "Card - 2",
                "Card - 3",
                "Card - 4",
                "Card - 5",
        };

        // 把卡片加入到卡片面板对象中,卡片(按钮)
        for (int i = 0; i < strings.length; i++) {
            cardPanel.add(strings[i], new Button(strings[i]));
        }

        // 放入卡片面板组件
        frame.add(cardPanel, BorderLayout.CENTER);

        // 创建一个panel对象用来存放按钮对象
        Panel buttonPanel = new Panel();

        // 创建翻阅用的按钮
        Button firstButton = new Button("first");
        Button previousButton = new Button("previous");
        Button thirdButton = new Button("third");
        Button nextButton = new Button("next");
        Button lastButton = new Button("last");

        // 监听按钮事件 重写的方法将会监听所有按钮,点击触发的事件将会封装到这个参数e对象中
        ActionListener actionListener = new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand(); // getActionCommand() 用来获取触发事件的按钮上的文字
                // 打印看看就知道了
                System.out.println(actionCommand);

                // 我们就可以根据按钮的字符来改变卡片的显示
                switch (actionCommand) {
                    case "first":
                        cardLayout.first(cardPanel);
                        break;
                    case "previous":
                        cardLayout.previous(cardPanel);
                        break;
                    case "third":
                        cardLayout.show(cardPanel, strings[2]); // 指定面板对象和指定具体的字符串
                        break;
                    case "next":
                        cardLayout.next(cardPanel);
                        break;
                    case "last":
                        cardLayout.last(cardPanel);
                        break;
                }

            }
        };

        // 将需要触发上述事件的按钮都添加这个监听对象
        firstButton.addActionListener(actionListener);
        previousButton.addActionListener(actionListener);
        thirdButton.addActionListener(actionListener);
        nextButton.addActionListener(actionListener);
        lastButton.addActionListener(actionListener);
        // 将按钮放入按钮面板对象中
        buttonPanel.add(firstButton);
        buttonPanel.add(previousButton);
        buttonPanel.add(thirdButton);
        buttonPanel.add(nextButton);
        buttonPanel.add(lastButton);
        
        // 按钮面板对象放入窗体的下面
        frame.add(buttonPanel, BorderLayout.SOUTH);

        // 自适应
        frame.pack();
        // 可视化
        frame.setVisible(true);
    }

}

6、盒子布局

java.awt.BoxLayout

由Swing引入,可以再垂直和水平方向上摆放GUI组件

构造器:

BoxLayout(Constainer target, int axis)

axis参数

BoxLayout.X_AXIS 水平
BoxLayout.Y_AXIS 垂直

案例:

package cn.dzz;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {
    public static void main(String[] args) {

        // 窗体
        Frame frame = new Frame();

        // 盒子布局 ,对窗体进行整体的布局
        BoxLayout boxLayout = new BoxLayout(frame, BoxLayout.Y_AXIS);

        // 设置布局
        frame.setLayout(boxLayout);

        // 添加两个按钮
        frame.add(new Button("Top-Button"));
        frame.add(new Button("Down-Button"));

        // 自适应
        frame.pack();
        // 可视化
        frame.setVisible(true);
    }
}

直接设置窗体为盒子布局太局限了,所以又提供了一个Box对象容器

Box对象默认就是BoxLayout布局,等同于Panel的作用一样

方法:

static Box createHorizontalBox() 创建水平排列的Box容器
static Box createVerticalBox() 创建垂直排列的Box容器

案例:

package cn.dzz;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {
    public static void main(String[] args) {
        // 窗体
        Frame frame = new Frame();
        // 创建水平盒子容器
        Box hBox = Box.createHorizontalBox();
        // 创建垂直盒子容器
        Box vBox = Box.createVerticalBox();
        // 放入窗体中
        frame.add(hBox, BorderLayout.NORTH);
        frame.add(vBox, BorderLayout.CENTER);
        
        // 水平盒子容器添加按钮
        Button hButton1 = new Button("h-button-1");
        Button hButton2 = new Button("h-button-2");
        hBox.add(hButton1);
        hBox.add(hButton2);
        
        // 垂直盒子容器添加按钮
        Button vButton1 = new Button("v-button-1");
        Button vButton2 = new Button("v-button-2");
        vBox.add(vButton1);
        vBox.add(vButton2);

        // 自适应
        frame.pack();
        // 可视化
        frame.setVisible(true);
    }
}

 

创建水平分割和垂直分割的间距对象

static Component createHorizontalGlue() 水平
static Component createVerticalGlue() 垂直

创建指定间距的间距对象

static Component createHorizontalStruct(int width) 固定宽度,高度可拉伸
static Component createVerticalStruct(int height) 固定高度,宽度可拉伸

案例:

package cn.dzz;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {
    public static void main(String[] args) {
        // 窗体
        Frame frame = new Frame();
        // 创建水平盒子容器
        Box hBox = Box.createHorizontalBox();
        // 创建垂直盒子容器
        Box vBox = Box.createVerticalBox();
        // 放入窗体中
        frame.add(hBox, BorderLayout.NORTH);
        frame.add(vBox, BorderLayout.CENTER);

        hBox.add(new Button("hButton-1"));
        // 创建一个分割的间距对象
        hBox.add(Box.createHorizontalGlue());

        hBox.add(new Button("hButton-2"));
        // 创建一个指定分割值10的间距对象
        hBox.add(Box.createHorizontalStrut(10));

        hBox.add(new Button("hButton-3"));

        // 垂直盒子的设置
        vBox.add(new Button("vButton-1"));

        // 垂直分割建立
        vBox.add(Box.createVerticalGlue());

        vBox.add(new Button("vButton-2"));

        // 指定高度的垂直分割
        vBox.add(Box.createVerticalStrut(10));

        vBox.add(new Button("vButton-3"));
        
        // 自适应
        frame.pack();
        // 可视化
        frame.setVisible(true);
    }
}

从运行的结果上可以看出来,当我们拖动窗体调整大小

Glue设置的大小会随着窗体大小的变化而变化

 

——1、常用组件

java.awt.Button 按钮
java.awt.Canvas 绘图画布
java.awt.Checkbox 复选框
java.awt.CheckboxGroup 复选框组
java.awt.Choice 下拉选择框
java.awt.Frame 窗口
java.awt.Label 标签
java.awt.List 列表框,添加多项条目
java.awt.Pane 不能单独存在基本容器类,必须放到其他容器中
java.awt.Scrollbar 滚动条
java.awt.ScrollPane 滚动条容器
java.awt.TextArea 多行文本域
java.awt.TextField 单行文本框

案例:

package cn.dzz;
import javax.swing.*;
import java.awt.*;

public class Main {
    public static void main(String[] args) {
        // 创建窗体
        Frame frame = new Frame();

        // 创建窗体中的组件,暂时先不设置布局
        TextArea textArea = new TextArea(5,20); // 文本框

        Choice choice = new Choice(); // 下拉选择框
        choice.add("red");  // 添加下拉选项
        choice.add("green");
        choice.add("yellow");

        CheckboxGroup checkboxGroup = new CheckboxGroup(); // 单选的选项组
        Checkbox cbxMale = new Checkbox("male", checkboxGroup, true); // 男性女性是一组的,不可多选
        Checkbox cbxFemale = new Checkbox("female", checkboxGroup, false);

        Checkbox cbxIsMarry = new Checkbox("isMarried"); // 是否已婚可选可不选

        List list = new List(6,true); // 列表
        list.add("red");
        list.add("green");
        list.add("blue");

        TextField textField = new TextField(20); // 文本输入框和按钮
        Button btnOk = new Button("ok"); // 确定按钮

        // 布局和组装
        Box cbxHorizontalBox = Box.createHorizontalBox(); // 下拉和单选一栏组装
        cbxHorizontalBox.add(choice);
        cbxHorizontalBox.add(cbxMale);
        cbxHorizontalBox.add(cbxFemale);
        cbxHorizontalBox.add(cbxIsMarry);

        Box sideVerticalBox = Box.createVerticalBox(); // 上下布局盒子
        sideVerticalBox.add(textArea); // 上面是文本框
        sideVerticalBox.add(cbxHorizontalBox); // 下面是单选和下拉

        Box topHorizontalBox = Box.createHorizontalBox(); // 最后再用一个大盒子左右合并装在一起
        topHorizontalBox.add(sideVerticalBox);
        topHorizontalBox.add(list);
        frame.add(topHorizontalBox, BorderLayout.CENTER);

        Box bottomHorizontalBox = Box.createHorizontalBox(); // 底部
        bottomHorizontalBox.add(textField);
        bottomHorizontalBox.add(btnOk);
        frame.add(bottomHorizontalBox, BorderLayout.SOUTH);

        // 可见 与 自适应
        frame.setVisible(true);
        frame.pack();
    }
}

案例效果:

 

 

posted @ 2021-02-03 14:33  emdzz  阅读(410)  评论(0编辑  收藏  举报