黑马程序员Java Swing笔记分享(AWT篇)

Swing 类库结构(这边建议边学边看这个图片就可以建立一定的思维导图)

        Swing 组件都采用 MVC(Model-View-Controller,即模型-视图-控制器)的设计,实现 GUI 组件的显示逻辑和数据逻辑的分离,从而允许程序员自定义 Render 来改变 GUI 组件的显示外观,以提供更多的灵活性。

        Swing 围绕 JComponent 组件构建,JComponent 则由 AWT 的容器类扩展而来。Swing 组织结构如图 1 所示。

一.AWT布局管理

(1)_awt_container容器_API

  • Study01(创建Frame窗口)

    public static void main(String[] args) {
        //创建窗口对象
        Frame frame=new Frame("window测试");
       // 创建窗口大小,位置
        frame.setLocation(100,100);
        frame.setSize(500,300);
        //设置窗口对象可见
        frame.setVisible(true);
    }
}

点击IDEA中的RUN,你可以得到一下窗口界面。

但是也有个问题我们需要手动在RUN中点掉暂停键,我们没办法关闭右上角的'X'(取消窗口) 。

  • Study02(创建Panel面板)

        Panel是面板,是一个很少直接使用的基本组件,或者继承重写,或者用来组织其他组件。
panel和Jpanel都为中间层容器,可显示文字、图像、绘制图形,主要功能是在GUI中组织其他组件。

public static void main(String[] args) {
        //1.创建一个window对象,因为,panel以及其他的容器,都不能独立存在,
        //必须依靠window存在
        Frame frame=new Frame();
        //2.创建一个Panel对象
        Panel p=new Panel();
        //3.创建一个文本框和按钮,并且放入到Panel容器中
        p.add(new TextField("测试文本"));
        p.add(new Button("这是一个测试按钮"));
        //4.把Pannel放入window中
        frame.add(p);
        //5.设置window的位置以及大小
        frame.setBounds(100,100,500,300);
        //6.设置window可见
        frame.setVisible(true);
    }

1.点击运行却又出现按钮中乱码现象。

2. 此时由于我们用的是UTF-8,故需要不让乱码出现,则点击下方图片选项

3. 点进去之后,直接Alt+V,在出现的VM options的方框里面添加这么一句话 :

4.-Dfile.encoding=gbk

5.然后再次运行即可。

 Study03(创建滚动窗格)

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

        //1.创建一个ScrollPane对象
        ScrollPane sp=new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
        //--->默认创建一个滚动条ScrollPane.SCROLLBARS_ALWAYS

        //2.往ScrollPane中添加内容
        sp.add(new TextField("测试文本"));
        sp.add(new Button("测试按钮"));

        //3.把ScrollPane添加到Frame中
        frame.add(sp);
        frame.setBounds(100,100,500,300);
        frame.setVisible(true);
    }

1.当然你运行的时候还是会有乱码出现,但问题不大,直接参考Study02蓝色字体。

 (2)_awt_LayoutManger布局管理

Study04(创建FlowLayout)

public static void main(String[] args) {
        Frame frame = new Frame("测试FlowLayout");
        //1.通过setLayout方法设置容器的布局管理器

        //1)向左边对齐
        frame.setLayout(new FlowLayout(FlowLayout.LEFT,20,20));//20为像素单位

        //2)向中间对齐
        frame.setLayout(new FlowLayout(FlowLayout.CENTER,20,20));//20为像素单位

        //3)向右边对齐
        frame.setLayout(new FlowLayout(FlowLayout.RIGHT, 40, 20));//20为像素单位

        //2.添加多个按钮到frame中
        for (int i = 0; i <= 100; i++) {
            frame.add(new Button("按钮" + i));
        }
        //3.设置最佳大小,pack方法
        frame.pack();
        frame.setVisible(true);
    }

 输出样例:向右的按钮输出

 Study05(创建BorderLayout)

 public static void main(String[] args) {
        Frame frame=new Frame("这里测试BorderLayout");

        //1.给frame设置BorderLayout布局管理器
        frame.setLayout(new BorderLayout(30,10));

        //2.往frame的指定区域添加组件
        frame.add(new Button("北侧按钮"),BorderLayout.NORTH);
        frame.add(new Button("南侧按钮"),BorderLayout.SOUTH);
        frame.add(new Button("东侧按钮"),BorderLayout.EAST);
        frame.add(new Button("西侧按钮"),BorderLayout.WEST);
        frame.add(new Button("中间按钮"),BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }

输出样例: 

 Study06(中间区域放文本)

public static void main(String[] args) {
        Frame frame=new Frame("这里测试BorderLayout");

        //1.给frame设置BorderLayout布局管理器
        frame.setLayout(new BorderLayout(30,10));

        //2.往frame的指定区域添加组件
        frame.add(new Button("北侧按钮"),BorderLayout.NORTH);
        frame.add(new Button("南侧按钮"),BorderLayout.SOUTH);
        frame.add(new Button("中间按钮"),BorderLayout.CENTER);

        frame.add(new TextField("测试文本"));

        frame.pack();
        frame.setVisible(true);
    }

输出样例:

         1.但是这样的话会将中间按钮给覆盖掉了,那么如何将按钮与测试文本共同放在中间且不互相干扰呢?

public static void main(String[] args) {
        Frame frame=new Frame("这里测试BorderLayout");

        //1.给frame设置BorderLayout布局管理器
        frame.setLayout(new BorderLayout(30,10));

        //2.往frame的指定区域添加组件
        frame.add(new Button("北侧按钮"),BorderLayout.NORTH);
        frame.add(new Button("南侧按钮"),BorderLayout.SOUTH);

        Panel p=new Panel();
        p.add(new Button("中间按钮"));
        p.add(new TextField("测试文本框"));
        frame.add(p);
        frame.pack();
        frame.setVisible(true);
    }

输出样例:

 Study07(创建GirdLayout)

如何做一个简单的计算器界面?

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

        //1、创建一个Panel对象,里面存放一个TextFiled组件
        Panel p=new Panel();
        p.add(new TextField(30));

        //2、把当前这个Panel添加到frame的北边区域
        frame.add(p,BorderLayout.NORTH);

        //3、创建一个Panel对象,并且设置他的布局管理器为GridLayout
        Panel p2=new Panel();
        p2.setLayout(new GridLayout(5,10,3,3));
        //4.往Panel中添加内容
        for(int i=0;i<10;i++){
            p2.add(new Button(i+""));
        }
        p2.add(new Button("+"));
        p2.add(new Button("-"));
        p2.add(new Button("*"));
        p2.add(new Button("/"));
        p2.add(new Button("."));

        //5.把当前Panel添加到frame中
        frame.add(p2);

        frame.pack();
        frame.setVisible(true);
    }

输出样例:

 Study08(创建CardLayout)

        什么是CardLayout,CardLayout布局管理器以时间而非空间来管理它的组件,它将容器的所有组件看成一叠卡片(每个卡片其实就是一个组件),每次只有最上面的Companent才可见。就好像一副扑克牌,它们叠在一起,每次只有最上面的一张扑克牌可见。

方法名称方法功能
CardLayout()创建默认的CardLayout布局管理器
CardLayout(int hgap,int vgap)通过指定卡片与容器左右边界的间距,上下边界间距来决定CardLayout的布局管理器
first(Container target)显示target容器中的第一张卡片
last(Container target)显示target容器中的最后一张卡片
previou(Container target)显示target容器中前一张卡片
next(Container target)显示target容器中的后一张卡片
show(Container target,String name)显示target容器中指定名字的卡片
public static void main(String[] args) {
        Frame frame=new Frame("测试CardLayout");

        //1、创建一个Panel容器,用来存储多张卡片
        Panel p1=new Panel();

        //2、创建一个CardLayout对象,并且把该对象设置给之前创建的Panel容器中
        CardLayout cardLayout=new CardLayout();
        p1.setLayout(cardLayout);

        //3、往Panel中储存多个组织
        String[] name={"第一张","第二张","第三张","第四张","第五张"};

        for(int i=0;i<name.length;i++){
            p1.add(name[i],new Button(name[i]));
        }

        //4、把Panel放到frame中的中间区域
        frame.add(p1);

        //5、创建另外一个panel p2,用来存储多个按钮组件
        Panel p2=new Panel();

        //6、创建5个按钮组件
        Button b1 = new Button("上一张");
        Button b2 = new Button("下一张");
        Button b3 = new Button("第一张");
        Button b4 = new Button("最后一张");
        Button b5 = new Button("第三张");

        //7、创建一个事件监听器,监听按钮的点击动作
        ActionListener listener=new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand();//这个字符串其实就是按钮上的文字
                switch (actionCommand){
                    case"上一张":
                        cardLayout.previous(p1);
                        break;
                    case"下一张":
                        cardLayout.next(p1);
                        break;
                    case"第一张":
                        cardLayout.first(p1);
                        break;
                    case"最后一张":
                        cardLayout.last(p1);
                        break;
                    case"第三张":
                        cardLayout.show(p1,"第三张");
                        break;

                }
            }
        };

        //8、把当前这个时间监听器和多个按钮绑定到一起
        b1.addActionListener(listener);
        b2.addActionListener(listener);
        b3.addActionListener(listener);
        b4.addActionListener(listener);
        b5.addActionListener(listener);

        //9、把按钮添加到容器p2中
        p2.add(b1);
        p2.add(b2);
        p2.add(b3);
        p2.add(b4);
        p2.add(b5);

        //10、把p2放到frame的南边区域
        frame.add(p2,BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
    }

样例输出:有点类似与windows中的图片浏览软件,可以来回切换上下张图片。

Study09(创建BoxLayout)

方法名称方法功能
BoxLayout(Container target,int axis)指定创建基于target容器的BoxLayout布局管理器,该布局管理器里的组件按照axis方向排列。其中axis有BoxLayout.X_AXIS(横向)和BoxLayout.Y_AXIS(纵向)两个方向
public static void main(String[] args) {
        Frame frame=new Frame();

        //1、基于frame容器,创建一个BoxLayout对象,并且,该对象存放的组件是垂直存放
        //BoxLayout boxLayout = new BoxLayout(frame, BoxLayout.Y_AXIS);
        //------>基于frame容器,创建一个BoxLayout对象,并且,该对象存放的组件是水平存放
        BoxLayout boxLayout = new BoxLayout(frame, BoxLayout.X_AXIS);

        //2、把BoxLayout对象设置给Frame
        frame.setLayout(boxLayout);

        //3、往frame中添加两个按钮组件
        frame.add(new Button("按钮1"));
        frame.add(new Button("按钮2"));

        frame.pack();
        frame.setVisible(true);
    }

样例输出:水平方向的按钮

 样例输出:垂直方向的按钮

Study10(创建容器Box)

        在Java.swing中,提供了一个新的容器Box,该容器的默认布局管理器就是BoxLayout,大多数形况下,Box容器去容纳多个GUI组件,然后再把Box容器作为一个组件,添加到其他的容器中,从而形成窗口布局。

方法名称方法功能
static Box createHorizontalBox()创建一个水平排列组件的Box容器
static Box creatVerticalBox()创建一个垂直排列组件的Box容器
public static void main(String[] args) {
        Frame frame = new Frame("测试BoxLayout");

        //1、创建一个水平排列组件的Box容器
        Box hBox = Box.createHorizontalBox();
        //2、往当前容器中添加两个按钮
        hBox.add(new Button("水平按钮1"));
        hBox.add(new Button("水平按钮2"));

        //3、创建一个垂直组件的Box容器
        Box vBox = Box.createVerticalBox();
        //4、往当前容器中添加两个按钮
        vBox.add(new Button("垂直按钮1"));
        vBox.add(new Button("垂直按钮2"));
        //5、把两个Box容器添加到FrameZ中展示
        frame.add(hBox, BorderLayout.NORTH);
        frame.add(vBox);

        frame.pack();
        frame.setVisible(true);
    }

样例输出:

但是这样的排布中间没有空隙, 那么怎么样让按钮之间有空隙呢?

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

        //1、创建水平排列的Box容器
        Box hbox = Box.createHorizontalBox();

        //2、往hBox容器中添加按钮,还需要在多个按钮之间添加分割
        hbox.add(new Button("水平按钮1"));
        hbox.add(Box.createHorizontalGlue());//该分割在两个方向上都可以拉伸
        hbox.add(new Button("水平按钮2"));
        hbox.add(Box.createHorizontalStrut(30));//水平2与水平3之间不能拉伸,固定死了
        hbox.add(new Button("水平按钮3"));

        //3、创建垂直排列的Box容器 vBox
        Box vBox = Box.createVerticalBox();

        //4、往vBox容器中添加按钮,还需要在多个按钮之间添加分割
        vBox.add(new Button("垂直按钮1"));
        vBox.add(Box.createVerticalGlue());//该分割在两个方向上都可以拉伸
        vBox.add(new Button("垂直按钮2"));
        vBox.add(Box.createVerticalStrut(30));//垂直按钮2与垂直按钮3之间是定死的,无论你怎么拉伸都不变
        vBox.add(new Button("垂直按钮3"));
        //5、把box容器中添加到frame中
        frame.add(hbox, BorderLayout.NORTH);
        frame.add(vBox);

        frame.pack();
        frame.setVisible(true);
    }

      样例输出:

 二.AWT中常用的组件

(1)_awt_常用基本组件

Study11(创建常用组件)

组件名功能
Button按钮
Canvas用于绘图的画布
Checkbox复选框组件(也可以当作单选框组件使用)
CheckboxGroup用于将多个Checkbox组件组合成一组,一组Checkbox组件将有只有一个可以被选中,即全部变成单选框组件
Choice下拉选择框
Frame窗口,在GUI程序里面通过该类创建窗口
Label标签类,用于放置提示性文本
List列表框组件,可以添加多个项目
Panel不能单独存在基本容器类,必须放到其他容器当中
Scrollbar滑动条组件,如果用户输入位于某个范围的值,就可以使用滑动条组件,比如调色板中设置RGB的三个值所用的滑动条。当创建一个滑动条时,必须指定它的方向、c初始值、滑块的大小、最小值以及最大值
ScrollPane带水平及垂直滚动条的容器组件
TextArea多行文本框
TextField单行文本框

        1.如何利用上面组件组装成下面的例子

public class day12 {
    //基本步骤:创建基本组件
    Frame frame = new Frame();

    TextArea te = new TextArea(5, 20);

    Choice colorchoice = new Choice();

    CheckboxGroup cbg = new CheckboxGroup();
    Checkbox male = new Checkbox("男", cbg, true);
    Checkbox female = new Checkbox("女", cbg, false);

    Checkbox isMarried = new Checkbox("是否已婚");

    TextField tf = new TextField(20);
    Button ok = new Button("确认");

    List colorList = new List(6, true);

    public void init() {
        //1、组装界面

        //2、组装底部
        Box bBox = Box.createHorizontalBox();
        bBox.add(tf);
        bBox.add(ok);

        frame.add(bBox, BorderLayout.SOUTH);

        //3、组装 选择部分
        colorchoice.add("蓝色");
        colorchoice.add("红色");
        colorchoice.add("绿色");

        Box cBox = Box.createHorizontalBox();
        cBox.add(colorchoice);
        cBox.add(male);
        cBox.add(female);
        cBox.add(isMarried);

        //4、组装文本域与选择部分
        Box topLeft = Box.createVerticalBox();
        //------->组装文本区域
        topLeft.add(te);
        //------->组装选择区域
        topLeft.add(cBox);

        //5、组装顶部左边和列表框
        colorList.add("蓝色");
        colorList.add("红色");
        colorList.add("绿色");

        Box top = Box.createHorizontalBox();
        top.add(topLeft);
        top.add(colorList);

        frame.add(top);

        //设置frame为最佳大小,并且可见
        frame.pack();
        frame.setVisible(true);


    }


    public static void main(String[] args) {
        new day12().init();//调用init方法
    }
}

 1.首先将需要的组件列出来

 2.将需要的组件组装起来

       ---->由上图可知先用一个box将下面的确定按钮以及文本区域组装在一起,并放在南边,由于文本区域与确定按钮是水平的,故用 :Box.createHorizontalBox()方法,组装为bBox

       ---->其次组装选择颜色的功能,由于也是与性别,已婚水平的也用Box.createHorizontalBox()方法,组装为cBox

       ---->组装最大文本域以及颜色选择,性别,已婚,由于二者是垂直关系,故用:Box.createVerticalBox()方法,将其组装成topLeft

       ---->最后例举colorlist,需要放在最top盒子的右边,那么再建造一个top盒子,将topLeft放在左边,colorlist放在右边,二者水平关系,用Box.createHorizontalBox()方法。

Study12(创建对话框Dialog)

        Dialog是window类的子类,是一个容器类,属于特殊组件。对话框是可以独立存在的顶级窗口,因此与普通窗口的用法几乎完全一样,但是使用对话框需要注意下面两点:

  • 对话框通常依赖其他窗口,就是通常需要有一个父类窗口
  • 对话框有非模式和模式两种,当某个模式对话框被打开后,该模式对话框总是位于它的父窗口之上,在模式对话框被关闭之前,父窗口无法获得焦点。
方法名称方法功能
Dialog(Frame owner,String title,boolean modal)

创建一个对话框对象:

onwer:当前对话框的父窗口

titile:当前对话框的标题

modal:当前对话框是否为模式对话框

1、什么是模式对话框?

        模态对话框(Modal Dialogue Box,又叫做模式对话框),是指在用户想要对对话框以外的应用程序进行操作时,必须首先对该对话框进行响应。所以无法对对话框以外的应用程序进行操作。

2、什么是非模式对话框

        非模态对话框允许用户在处理非模态对话框的同时处理目标对话框。其实与上面的内容反之即可。

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

        //1.创建两个对话框Dialog对象,一个模式,一个非模式
        Dialog d1 = new Dialog(frame, "模式对话框", true);
        Dialog d2=new Dialog(frame,"非模式对话框",false);

        //2、通过setBounds方法设置Dialog的位置与大小
        d1.setBounds(20,30,300,200);
        d2.setBounds(20,30,300,200);

        //3、创建两个按钮
        Button b1=new Button("打开模式对话框");
        Button b2=new Button("打开非模式对话框");
        //4、需要给这两个按钮添加点击后的行为(AWT事件)
        b1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                d1.setVisible(true);
            }
        });

        b2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                d2.setVisible(true);
            }
        });

        //5、把按钮添加到frame中
        frame.add(b1,BorderLayout.NORTH);
        frame.add(b2);

        frame.pack();
        frame.setVisible(true);
    }

 3、但是如何添加组件到对话框里面去呢?

        其实很简单只需要将基本组件装到Box中在将Box中的对象添加到对话框即可。

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

        //1.创建两个对话框Dialog对象,一个模式,一个非模式
        Dialog d1 = new Dialog(frame, "模式对话框", true);
        
        //----->创建一个垂直的Box容器,把一个文本框以及确定按钮放在Box容器中
        Box vbox=Box.createVerticalBox();
        vbox.add(new TextField(20));
        vbox.add(new Button("确认"));
    
            //----->将vbox放在d1中去
        d1.add(vbox);
        //2、通过setBounds方法设置Dialog的位置与大小
        d1.setBounds(20,30,300,200);
        

        //3、创建两个按钮
        Button b1=new Button("打开模式对话框");
       
        //4、需要给这两个按钮添加点击后的行为(AWT事件)
        b1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                d1.setVisible(true);
            }
        });
        

        //5、把按钮添加到frame中
        frame.add(b1,BorderLayout.NORTH);
       

        frame.pack();
        frame.setVisible(true);
    }

Study13(创建对话框FileDialog)

        Dialog类中还有一个子类:FileDialog,它代表一个文件对话框,用于打开或者保存文件,需要注意的是FileDialog无法指定模态还是非模态,这是因为FileDialog依赖于运行平台的实现,如果运行平台的为文件对话框是模态的,那么FileDialog也是模态的;否则就是非模态的。

方法名称方法功能
FileDialog(Frame parent,String title.int mode)

创建一个文件对话框:

parent:指定父窗口

title:对话框标题

mode:文件对话框类型,如果指定为FileDialog.LOAD,用于打开文件,如果指定为FileDialog.SAVE,用于保存文件

String getDirectory()获取被打开或保存文件的绝对路径
String getFile()获取被打开或保存文件的文件名
public static void main(String[] args) {
        Frame frame = new Frame();
        //1、创建两个FileDialog对象
        FileDialog fileDialog = new FileDialog(frame, "选择要打开的文件", FileDialog.LOAD);
        FileDialog fileDialog1 = new FileDialog(frame, "选择要保存的文件", FileDialog.SAVE);

        //2、创建两个按钮
        Button b1 = new Button("打开文件");
        Button b2 = new Button("保存文件");

        //3、给这两个按钮设置点击后的行为:获取打开或者保存的路径文件名
        b1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                fileDialog.setVisible(true);//代码会阻塞到这里

                //获取选择的路径及文件
                String directory = fileDialog.getDirectory();
                String file = fileDialog.getFile();
                System.out.println("打开的文件路径为:" + directory);
                System.out.println("打开的文件名称为:" + file);

            }
        });
        b2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                fileDialog1.setVisible(true);

                //获取选择的路径及文件
                String directory = fileDialog1.getDirectory();
                String file = fileDialog1.getFile();
                System.out.println("打开的文件路径为:" + directory);
                System.out.println("打开的文件名称为:" + file);
            }
        });

        //4、把按钮添加到Frame中
        frame.add(b1, BorderLayout.NORTH);
        frame.add(b2);

        frame.pack();
        frame.setVisible(true);
    }

样例输出:

Study14(创建事件处理)

1)定义:当在某个组件上发生某些操作的时候,会自动的触发-段代码的执行。
2)在GUI事件处理机制中涉及到4个重要的概念需要理解:
        事件源(Event Source) :操作发生的场所,通常指某个组件,例如按钮、窗口等;
        事件( Event) : 在事件源上发生的操作可以叫做事件, GUI会把事件都封装到一个Event对象中 ,如果需要知道该事件的详细信息,就可以通过Event对象来获取。
        事件监听器(Event Listener):当在某个事件源上发生了某个事件,事件监听器就可以对这个事件进行处理。
        注册监听:把某个事件监听器(A)通过某个事件(B)绑定到某个事件源(C)上,当在事件源C上发生了事件B之后,那么事件监听器A的代码就会自动执行。 

了解了上面机制,那么要如何实现下面图片呢,点击确定会有hello world出现?

------->

-------> 

public class day15 {
    Frame frame=new Frame();

    TextField tf = new TextField(30);
    Button ok = new Button("确定");

    public void init(){
        //组装视图

        //监听器
        //MyListener myListener=new MyListener();
        //注册监听
        ok.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                tf.setText("hello world");
            }
        });

        //把tf和ok放到Frame中
        frame.add(tf,BorderLayout.NORTH);
        frame.add(ok);

        frame.pack();
        frame.setVisible(true);
    }
//    private class MyListener implements ActionListener {
//
//        @Override
//        public void actionPerformed(ActionEvent e) {
//            tf.setText("hello world");
//        }
//    }

    public static void main(String[] args) {
        new day15().init();
    }

 Study15(常见事件和事件监听器)

        事件监听器必须实现事件监听器接口,AWT提供了大量的事件监听器接口用于实现不同类型的事件监听器,用于监听不同类型的事件。AWT中提供了丰高的事件类,用于封装不同组件上所发生的特定操作, AWT的事件类都是AWTEvent类的子类,AWTEvent是EventObject的子类。

1、AWT把事件分为了两大类:
        1)低级事件:这类事件是基于某个特定动作的事件。比如进入。点击、拖放等动作的鼠标事件,再比如得到焦点和失去焦点等焦点事件。

事件触发时机
ComponentEvent组件事件,当组件尺寸发生变化、位置发生移动、显示/陶藏状态发生改变时触发该事件。
ContainerEvent容器事件,当容器里发生添加组件、删除组件时触发该事件。
WindowEvent窗口事件,当窗口状态发生改变(如打开、关闭。最大化、最小化)时触发该事件。
FocusEvent焦点事件,当组件得到焦点或失去焦点时触发该事件。
KeyEvent键盘事件,当按键被按下、松开、单击时触发该事件。
MouseEvent鼠标事件,当进行单击、按下、松开、移动鼠标等动作时触发该事件。
PaintEvent组件绘制事件。该事件是一个特殊的事件类型 ,当GUI组件调用update/paint方法来呈现自身时触发该事件,该事件并非专用于事件处理模型。

        2)高级事件:这类事件并不会基于某个特定动作,而是根据功能含义定义的事件。

事件触发时机
ActionEvent动作事件,当按钮、菜单项被单击,在TextField中按Enter键时触发。
AjustmentEvent调节事件,在滑动条上移动滑块以调节数值时触发该事件。
ItemEvent选项事件,当用户选中某项,或取消选中某项时触发该事件。
TextEvent文本事件,当文本框、文本域里的文本发生改变时触发该事件。

2、事件监听器
        不同的事件需要使用不同的监听器监听,不同的监听器需要实现不同的监听器接口,当指定事件发生后,事件监听器就会调用所包含的事件处理器(实例方法)来处理事件。

3、案例一:

public static void main(String[] args) {
        Frame frame=new Frame("测试监听器");
        //创建组件(事件源)
        TextField tf=new TextField();
        Choice names=new Choice();
        names.add("刘岩");
        names.add("舒淇");
        names.add("闫妮");

        //给文本添加TextListener,监听内容变化
        tf.addTextListener(new TextListener() {
            @Override
            public void textValueChanged(TextEvent e) {
                String text = tf.getText();
                System.out.println("当前文本的内容为:"+text);
            }
        });

        //给下拉选择框添加ItemListener,监听条目选项的变化
        names.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                Object item = e.getItem();
                System.out.println("当前选中的条目为:"+item);
            }
        });

        //给frame注册ContainerListener监听器,监听容器组件的添加
        frame.addContainerListener(new ContainerListener() {
            @Override
            public void componentAdded(ContainerEvent e) {//添加方法
                Component child = e.getChild();
                System.out.println("frame中添加了:"+child);
            }

            @Override
            public void componentRemoved(ContainerEvent e) {//移除方法

            }
        });


        //添加到frame中
        Box hBox=Box.createHorizontalBox();
        hBox.add(names);
        hBox.add(tf);
        frame.add(hBox);

        //设置frame最佳大小并可见

        frame.pack();
        frame.setVisible(true);


    }

 样例输出:

每次点击都会记录下监听内容: 

 

4、 案例二:如何关闭右上角x键

public static void main(String[] args) {

        Frame frame=new Frame("测试WindowListener");
        frame.setBounds(200,200,500,300);

        //设置WindowListener,监听用户点击右上角X的动作,则关闭窗口
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        frame.setVisible(true);
    }

样例输出:

 Study16(创建菜单组件)

        前面讲了GUI界面的构建,其实就是把一些GUI的组件,按照一定的布局放在容器即可。在实际开发中,除了主界面,还有一类比较重要的内容就是菜单相关组件,可以通过菜单相关组件很方便的使用特定的功能,在AWT中,菜单组件的使用和之前学习的组件时一模一样的,只需要把菜单条、菜单、菜单项组合在一起,按照一定的布局,放入到容器中即可。

菜单组件名称功能
MenuBar菜单条,菜单的容器
Menu菜单组件,菜单项的容器。它也是MenuItem的子类,所以可作为菜单项使用
PopupMenu菜单项组件
MenuItem菜单项组件
CheckboxMenuItem复选框菜单项组件

菜单相关组件使用: 

        1、准备菜单项组件,这些组件可以是MenuItem及子类对象

        2、准备菜单组件Menu或者PopupMenu(右击弹出子菜单),把第一步中准备好的菜单项组件添加进来

        3、准备菜单条组件MenuBar,把第二步准备好的菜单组件Menu添加进来

        4、把第三步中准备好的菜单条组件添加到窗口对象中显示

小技巧:

        1、如果要在某个菜单的菜单项之间添加分割线,那么只需要调用Menu的add(new MenuItem("-"))即可。

        2、如果要给某个菜单项关联快捷键功能,那么只需要在创建菜单项对象设置即可,例如给菜单项关联ctrl+shift+Q快捷键,只需要:new MenuItem("菜单项名字",new MenuShortcut(KeyEvent.VK_Q,true);

案例一:如何做出下图呢?

------->

-------> 

public class day18 {
    //创建窗口
    private Frame frame = new Frame();

    //创建菜单条
    MenuBar menuBar = new MenuBar();

    //创建菜单组件
    Menu fileMenu = new Menu("文件");
    Menu editMenu = new Menu("编辑");
    Menu formatMenu = new Menu("格式");


    //菜单项组件
    MenuItem auto = new MenuItem("菜单换行");
    MenuItem copy = new MenuItem("复制");
    MenuItem paste = new MenuItem("粘贴");

    //关联快捷键
    MenuItem comment = new MenuItem("注释", new MenuShortcut(KeyEvent.VK_Q, true));
    MenuItem canceComment = new MenuItem("取消注释");

    TextArea ta = new TextArea(6,40);

    public void init() {
        //组装视图
        comment.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //在监听器下e.getActionCommand()点击后最后都返回注释功能
                ta.append("您点击菜单项:" + e.getActionCommand()+"\n");
            }
        });

        formatMenu.add(comment);
        formatMenu.add(canceComment);

        //组装编辑菜单
        editMenu.add(auto);
        editMenu.add(copy);
        editMenu.add(paste);
        editMenu.add(formatMenu);

        //组装菜单条
        menuBar.add(fileMenu);
        menuBar.add(editMenu);

        //把菜单条放入到Frame中
        frame.setMenuBar(menuBar);
        frame.add(ta);

        //设置frame最佳大小
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {

        new day18().init();

 案例二:通过PopupMenu实现下图效果

实现思路:

1、创建PopupMenu菜单组件

2、创建多个MenuItem菜单项,并添加到PopupMenu中

3、将PopupMenu添加到目标组件中

4、为需要右击出现PopupMenu菜单的组件,注册鼠标监听事件,当监听到用户释放右键时,弹出菜单。

public class day19 {
    private Frame frame=new Frame("这里测试PopupMenu");

    //创建文本域
    TextArea ta=new TextArea("我爱中华",6,40);

    //创建Panel容器
    Panel p=new Panel();

    //创建PopupMenu
    PopupMenu popupMenu=new PopupMenu();

    //创建菜单项
    MenuItem comment=new MenuItem("注释");
    MenuItem cancalcomment=new MenuItem("取消注释");
    MenuItem copy=new MenuItem("复制");
    MenuItem save=new MenuItem("保存");


    public void init(){
        //组装视图
        ActionListener listener=new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String actionCommand = e.getActionCommand();
                ta.append("您点击了右键:"+actionCommand+"\n");
            }
        };

        //传入监听器
        comment.addActionListener(listener);
        cancalcomment.addActionListener(listener);
        copy.addActionListener(listener);
        save.addActionListener(listener);

        //将功能放到popupMenu当中去
        popupMenu.add(comment);
        popupMenu.add(cancalcomment);
        popupMenu.add(copy);
        popupMenu.add(save);

        //将popupMenu放到面板中Panel中去
        p.add(popupMenu);

        //设置Panel的大小
        p.setPreferredSize(new Dimension(40,100));

        //给Panel注册鼠标事件,监听用户释放鼠标的动作,展示菜单
        p.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                //isPopupTrigger()用来判断是否为鼠标右键点击
                boolean flag = e.isPopupTrigger();
                if(flag){
                    //显示popupMenu
                    popupMenu.show(p,e.getX(),e.getY());
                }
            }
        });
        frame.add(ta);
        frame.add(p,BorderLayout.SOUTH);

        //设置frame最佳大小,并可视化
        frame.pack();
        frame.setVisible(true);
    }



    public static void main(String[] args) {
        new day19().init();
    }
}

 Study17(绘图)

        很多程序如各种游戏需要在窗口中绘制各种图形,除此之外,及时要开发JavaEE项目时,有时候也必须"动态"地向客户端生成各种图形、图标,比如:图形验证码、统计图等,这都需要利用AWT地绘图功能。

组件绘图原理:

        之前我们已经学习很多组件,如:Button、Frame、Checkbox等等,不同的组件,展示出来的图形都不一样,其实这些组件展示出来的图形,其本质就是用AWT的绘图完成。

        在AWT中,真正提供绘图功能的是Graphics对象,那么Component组件和Graphics对象存在什么关系,才能让Component绘制呢?在Component类中,提供了下列三个方法来完成组件图案的绘制于刷新;

        paint(Graphics g):绘制组件的外观;

        update(Graphics g):内部调用paint方法,刷新组件外观;

        repaint():调用update方法,刷新组件外观;

        一般情况下,update和paint方法是由AWT系统负责调用,如果程序要希望系统重新绘制组件,可以调用repaint方法完成。 

1、Graphics对象的使用

        实际生活中如果需要画图,首先我们得准备一张纸,然后在拿一支笔,配和一些颜色,就可以在纸上画出来各种各样的图形,例如:圆形、矩形等等。

        程序绘图也一样,也需要画布,画笔,颜料等等。AWT中提供了Canvas类充当画布,提供Graphics类来充当画笔,通过调用Graphics对象的setColor()方法可以给画笔设置颜色。

2、画图的步骤

        1.自定义类,继承Canvas类,重写paint(Graphics g)方法完成画图。

        2.在paint方法内部,真正开始画图之前调用Graphics对象的setColor()、setFont()等方法设置画笔的颜色,字体等属性;

        3.调用Graphics画笔的drawXxx()方法开始画图。

        其实画图的核心就在使用Graphics画笔在Canvas画布上画出什么颜色、什么样式的图形,什么样式的图形,所以核心在画笔上,下表中列出了Graphics类中常用的一些方法:

方法名称方法功能
setColor(Color c)设置颜色
setFont(Font font)设置字体
drawLine()绘制直线
drawRect()绘制矩形
drawRoundRect()绘制圆角矩形
drawOval()绘制椭圆形
drawPolygon()绘制多边形
drawArc()绘制圆弧
drawPolyline绘制折线
fileRect()填充圆角矩形区域
fillRoundRect()填充圆角矩形区域
fillOval()

填充椭圆区域 

fillPolygon()填充多边形区域
fillArc()填充圆弧对应的扇形区域
drawImage()绘制位图

3、案例一:按钮点击成图像

------>

------> 

------> 

public class day20 {
    //定义一个RECT_SHAPE以及OVAL_SHAPE当点击按钮的时候监听器打开,将二者分别进行赋值操作
    private final String RECT_SHAPE = "reat";
    private final String OVAL_SHAPE = "oval";

    private Frame frame = new Frame("测试绘图");

    Button butreat = new Button("绘制矩形");
    Button butoval = new Button("绘制椭圆");

    //定义一个变量,记录当前要绘制椭圆还是矩形
    private String shape = "";

    //1、自定义类,继承Canvas,重写paint(Graphics g)方法完成画图;
    private class Mycnvas extends Canvas {
        @Override
        public void paint(Graphics g) {
            //绘制不同的图形
            if (shape.equals(RECT_SHAPE)) {
                //绘制矩形
                g.setColor(Color.BLACK);//设置当前画笔的颜色
                g.drawRect(100, 100, 150, 100);
            } else if (shape.equals(OVAL_SHAPE)) {
                //绘制椭圆
                g.setColor(Color.RED);
                g.drawOval(100, 100, 150, 100);
            }

        }
    }

    //创建自定义的画布对象
    Mycnvas drawArea = new Mycnvas();

    public void init() {
        //当我点击绘制矩形的时候,就会执行监听器代码
        butreat.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //将定义的RECT_SHAPE赋值给shape
                shape = RECT_SHAPE;
                //并且在画布中repaint()
                drawArea.repaint();
            }
        });
        //当我点击绘制椭圆的时候,就会执行监听器代码
        butoval.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //将定义的OVAL_SHAPE赋值给shape
                shape = OVAL_SHAPE;
                drawArea.repaint();
            }
        });

        //创建Panel,承载按钮
        Panel p = new Panel();
        p.add(butoval);
        p.add(butreat);

        frame.add(p, BorderLayout.SOUTH);

        //drawArea的大小需要设置
        drawArea.setPreferredSize(new Dimension(300, 300));
        frame.add(drawArea);

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


    public static void main(String[] args) {
        new day20().init();
    }
}

4、案例二:弹射小球 (非常有意思,建议自己手动敲一遍理解原理)    

        Java也可以用来开发一些动画。所谓动画,就是间隔一定的时间(通常小于0.1秒)重新绘制的图形,两次绘制的图像之间差异比较小,肉眼看起来就成为所谓的动画。

        为了实现间隔一定的时间就重新调用组件的repain方法,可以借助Swing提供的Timer类,Timer类是一个定时器,它有如下一个构造器:

        Timer(int delay,ActionListener):每间隔delay毫秒,系统自动触发ActionLinster监听器的事件处理器的方法,在方法内部我们就可以调用组件的repaint方法,完成组件重新绘制。

----->

----->  

package javaswing;


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

public class day21 {
    private Frame frame = new Frame("弹球游戏");

    //设置桌面宽度
    private final int TABLE_WIDTH = 300;
    //设置桌面高度
    private final int TABLE_HEIGHT = 400;

    //球拍的高度和宽度
    private final int RACKET_WIDTH = 60;
    private final int RACKET_HEIGHT = 20;

    //小球的大小
    private final int BALL_SIZE = 16;

    //定义变量,记录小球的坐标
    private int ballX = 120;
    private int ballY = 20;

    //定义变量,记录小球在x和y方向上分别移动的速度
    private int speedY = 10;
    private int speedX = 5;

    //定义变量,记录球拍的坐标
    private int racketX = 120;
    private final int racketY = 340;//y坐标固定不变的,只会在左右移动

    //定义变量,标识当前游戏是否结束
    private boolean isOver = false;

    //声明一个定时器
    private Timer timer;

    //自定义一个类,继承canvas,充当画布
    private class Mycanvas extends Canvas {
        //记得重写paint
        @Override
        public void paint(Graphics g) {
            //TODO 在这里绘制内容
            if (isOver) {
                //游戏结束的内容
                g.setColor(Color.RED);
                g.setFont(new Font("Times", Font.BOLD, 30));
                g.drawString("游戏结束!", 50, 200);
            } else {
                //游戏进行的内容

                //绘制小球
                g.setColor(Color.BLUE);
                g.fillOval(ballX, ballY, BALL_SIZE, BALL_SIZE);
                //绘制球拍
                g.setColor(Color.PINK);
                g.fillRect(racketX, racketY, RACKET_WIDTH, RACKET_HEIGHT);
            }
        }
    }

    //创建绘画区域
    Mycanvas drawArea = new Mycanvas();

    //组件组装方法
    public void init() {
        //组装视图,以及游戏逻辑的控制
        //----->球拍的控制逻辑
        //----->小球的控制逻辑

        //完成球拍坐标的变化(创建监听器)(按键事件)(键盘事件)
        KeyListener listener = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {

                //获取当前按下的键
                int keyCode = e.getKeyCode();//我们的键盘每一个键位都对应一个整数keycode

                if (keyCode == KeyEvent.VK_LEFT) {

                    //应该向左移动
                    if (racketX > 0) {
                        racketX -= 10;
                    }
                }
                if (keyCode == KeyEvent.VK_RIGHT) {

                    //应该向右移动
                    if (racketX < (TABLE_WIDTH - RACKET_WIDTH)) {
                        racketX += 10;
                    }
                }
            }
        };

        //给frame和drawArea注册监听器
        frame.addKeyListener(listener);
        drawArea.addKeyListener(listener);

        //小球坐标的控制
        ActionListener task = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //更新小球的坐标,重绘界面

                //根据边界范围,修正速度
                //----->修正x轴弹出碰到边界的方向
                if (ballX <= 0 || ballX >= (TABLE_WIDTH - BALL_SIZE)) {
                    speedX = -speedX;
                }
                //----->修正y轴弹出碰到边界的方向
                if (ballY <= 0 || ballY > racketY - BALL_SIZE && ballX > racketX && ballX < racketX + RACKET_WIDTH) {
                    speedY = -speedY;
                }
                //----->超出球拍往下,游戏结束
                if (ballY > racketY - BALL_SIZE && (ballX < racketX || ballX > racketX + RACKET_WIDTH)) {
                    //当前小球超出了球拍范围

                    //停止定时器
                    timer.stop();
                    //修改游戏是否结束标记
                    isOver = true;
                    //重新绘制界面
                    drawArea.repaint();

                }

                ballX += speedX;
                ballY += speedY;

                //重新绘制界面
                drawArea.repaint();

            }
        };

        //这里需要手动导包import javax.swing.Timer.*;
        timer = new Timer(100, task);
        timer.start();

        drawArea.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));
        frame.add(drawArea);

        //frame窗口关闭
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        //frame最佳大小
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new day21().init();
    }

Study18(处理位图)

        如果仅仅绘制一些简单的几何图形,程序的图形依旧十分简单。AWT允许在组件上绘制位图,Graphics提供了drawmage(Image image)方法用于绘制位图,该方法需要一个Image参数一一代表位图,通过该方法就可以绘制出指定的位图。

位图使用步骤:

1、创建Image的子类对象BufferedImage(int width,int heigth,int ImageType),创建时需要指定位图的宽高及类型属性;此时相当于在内存中生成了一张图片;

2、调用BufferedImage对象的getGraphics()方法获取画笔,此时就可以往内存中的这张图片上绘图了,绘图的方法和之前学习的一样。

3、调用组件paint()方法中提供的Graphics对象的drawImage()方法,一次性的内存中的图片BufferedImage绘制到待定的组件上。

使用位图绘制组件的好处:

使用位图来绘制组件,相当于实现了图的缓冲区,此时绘图时没有直接把图形绘制到组件上,而是先绘制到内存中的BufferedImage上,等全部绘制完成后,再一次性的图像显示到组件上即可,这样用户的体验会好很多。

案例:

绘画不精,望谅解,重点是:

drawArea.addMouseMotionListener与drawArea.addMouseListener的区别,我就是在这里踩坑的。

drawArea.addMouseMotionListener指的是按下鼠标移动的

drawArea.addMouseListener值的是不移动鼠标的

 

public class day22 {
    private Frame frame = new Frame("简单绘图工具");

    //定义画图区域的宽高
    private final int AREA_WIDTH = 500;
    private final int AREA_HEIGHT = 400;


    //定义一个右键菜单,用于设置画笔的颜色,PopupMenu为鼠标右击
    private PopupMenu colorMenu = new PopupMenu();
    private MenuItem reditem = new MenuItem("红色");
    private MenuItem buleitem = new MenuItem("蓝色");
    private MenuItem greenitem = new MenuItem("绿色");

    //定义一个变量记录当前画笔的颜色
    private Color forceColor = Color.BLACK;

    //创建一个BufferImage位图对象
    BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_RGB);

    //通过位图,获取关联的Graphics对象
    Graphics g = image.getGraphics();

    //自定义一个类,继承Canvas
    private class MyCanvas extends Canvas {
        @Override
        public void paint(Graphics g) {
            g.drawImage(image, 0, 0, null);
        }
    }

    //取自定义类中对象drawArea绘图区域
    MyCanvas drawArea = new MyCanvas();

    //定义一个变量,记录鼠标在拖动过程中上一次所处的坐标
    private int preX = -1;
    private int preY = -1;

    //组装方法
    public void init() {
        //组装视图,逻辑控制
        ActionListener actionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //e.getActionCommand()获取的是new MenuItem("红色")中的“红色”
                String actionCommand = e.getActionCommand();
                switch (actionCommand) {
                    case "红色":
                        forceColor = Color.RED;
                        break;
                    case "蓝色":
                        forceColor = Color.BLUE;
                        break;
                    case "绿色":
                        forceColor = Color.GREEN;
                        break;
                }
            }
        };

        //将按钮添加监听器并使之进行监听
        reditem.addActionListener(actionListener);
        buleitem.addActionListener(actionListener);
        greenitem.addActionListener(actionListener);

        //colorMenu
        colorMenu.add(reditem);
        colorMenu.add(buleitem);
        colorMenu.add(greenitem);

        //把colorMenu放在绘图区域
        drawArea.add(colorMenu);

        drawArea.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {//当鼠标抬起时被调用
                boolean popupTrigger = e.isPopupTrigger();
                if (popupTrigger) {
                    //将colorMenu在drawArea展现出来,鼠标点击的x与y轴位置
                    colorMenu.show(drawArea, e.getX(), e.getY());
                }

            }

        });

        //设置位图背景为白色
        g.setColor(Color.white);
        g.fillRect(0, 0, AREA_WIDTH, AREA_HEIGHT);

        //通过监听鼠标的移动,完成线条绘制
        drawArea.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                if (preX != -1 && preY != -1) {
                    g.setColor(forceColor);
                    //画线条,需要两组坐标,分别代表起点与终点,e.getX(),e.getY()可以获取坐标
                    g.drawLine(preX, preY, e.getX(), e.getY());
                }
                //修正preX与preY的值
                preX = e.getX();
                preY = e.getY();


                //重绘组件
                drawArea.repaint();

            }
        });
        drawArea.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                //重置preX和preY
                preX = -1;
                preY = -1;
            }
        });
        //将绘画区域设置为最合适的区域
        drawArea.setPreferredSize(new Dimension(AREA_WIDTH, AREA_HEIGHT));
        frame.add(drawArea);

        //设置frame最佳大小并可见
        frame.pack();
        frame.setVisible(true);
    }


    public static void main(String[] args) {
        new day22().init();
    }
}

Study19 ImageIO的使用

在实际生活中,很多软件都支持打开本地磁盘已经存在的图片进行编辑,编辑完毕后,再重新保存到本地磁盘。如果使用AWT要完成这样的功能,那么需要使用到ImageIO类,可以操作本地磁盘的图片文件。

方法名称方法功能
static BufferedImage read(File input)读取本地磁盘图片文件
static BufferedImage read(InputStream input)读取本地磁盘图片文件
static boolean write(RenderedImage im,String formatName,File  output)往本地磁盘中输出图片文件

案例一:制作图片查看器

package javaswing;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class day23 {
    private Frame frame = new Frame("图片查看器");

    //创建菜单条
    MenuBar menuBar = new MenuBar();
    //创建菜单
    Menu menu = new Menu("文件");
    //创建菜单中的菜单名
    MenuItem open = new MenuItem("打开");
    MenuItem save = new MenuItem("另存为");

    //声明BufferImage对象,记录本地存取到内存的图片,到最后读入文件,直接赋值给image
    BufferedImage image;

    private class MyCanvas extends Canvas {
        @Override
        public void paint(Graphics g) {
            g.drawImage(image, 0, 0, null);
        }
    }

    MyCanvas drawArea = new MyCanvas();

    public void init() {
        //组装视图

        open.addActionListener(e -> {
            //打开一个文件对话框
            FileDialog fileDialog = new FileDialog(frame, "打开图片", FileDialog.LOAD);
            fileDialog.setVisible(true);

            //获取用户选择的图片路径以及名称
            String dir = fileDialog.getDirectory();
            String fileName = fileDialog.getFile();

            try {
                //记得这里要写IO读入的文件,并且赋值给image
                image = ImageIO.read(new File(dir, fileName));
                drawArea.repaint();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });

        save.addActionListener(e -> {
            //获取用户设置的保存路径以及文件名称

            FileDialog fileDialog = new FileDialog(frame, "保存图片", FileDialog.SAVE);
            fileDialog.setVisible(true);

            //展示用户设置的保存路径以及文件名称
            String dir = fileDialog.getDirectory();
            String fileName = fileDialog.getFile();

            try {
                //注意这里要写写”JPEG“,文件格式名
                ImageIO.write(image, "JPEG", new File(dir, fileName));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });

        //将打开文件以及保存文件放到menu组件中
        menu.add(open);
        menu.add(save);

        //将menu组件放在菜单栏中
        menuBar.add(menu);

        //把菜单条放在窗口中
        frame.setMenuBar(menuBar);
        frame.add(drawArea);

        //自定义frame的框架,并且可见
        frame.setBounds(200, 200, 740, 508);
        frame.setVisible(true);

        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

    }

    public static void main(String[] args) {
        new day23().init();
    }
}


 

  • 5
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值