Java学习记录 Day19(NIO流、GUI编程)

Day 19

2019年5月25日。
这是我学习Java的第十九天。
这一天,我学到了以下的知识。

NIO流

NIO流,是面向缓冲区的,基于通道的IO操作,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多
以下,用一个文件复制类copyFile来说明NIO流。copyFile执行三个基本的操作:创建一个Buffer,然后从源文件读取数据到缓冲区,然后再将缓冲区写入目标文件。
详细的NIO流说明,可以参考:https://www.cnblogs.com/zailushang1996/p/8916017.html

public static void copyFile(String src,String dst) throws IOException{
        //声明源文件和目标文件
        FileInputStream fi=new FileInputStream(new File(src));
        FileOutputStream fo=new FileOutputStream(new File(dst));
        //获得传输通道channel
        FileChannel inChannel=fi.getChannel();
        FileChannel outChannel=fo.getChannel();
        //获得容器buffer
        ByteBuffer buffer=ByteBuffer.allocate(1024);
        while(true){
        //判断是否读完文件
        int eof =inChannel.read(buffer);
        if(eof==-1){
        break;
        }
        //重设一下buffer的position=0,limit=position
        buffer.flip();
        //开始写
        outChannel.write(buffer);
        //写完要重置buffer,重设position=0,limit=capacity
        buffer.clear();
        }
        inChannel.close();
        outChannel.close();
        fi.close();
        fo.close();
}

GUI编程

GUI,即Graphical User Interface(图形用户接口编程),是指采用图形方式显示的计算机操作用户界面。
Java中的GUI编程,基本上是运用swing和AWT,在这里主要介绍AWT:

  • AWT(Abstract Window Toolkit)包括了很多类和接口,用于Java Application的GUI(Graphics User Interface 图形用户界面)编程
  • GUI的各种元素(如:窗口,按钮,文本框等)由Java类来实现
  • 使用AWT所涉及的类一般在Java.AWT包及其子包中
  • Container(容器)和Component(组件)是AWT中的两个核心类

Container和Component的关系图,如下所示:
在这里插入图片描述
接下来,分别介绍Container和LayoutManager(布局管理器)以及Component来说明GUI编程

  • Container(容器)
    Container里面分为Window和Pannel。
    Window是可以独立显示出来的,平时我们看到的各种各样的应用程序的窗口都可以称为Window,Window作为一个应用程序窗口独立显示出来。Window本身又可以分为Frame和Dialog,Frame就是我们平时看到的一般的窗口,而Dialog则是那些需要用户进行了某些操作(如点击某个下拉菜单的项)才出现的对话框,这种对话框就是Dialog。
    Pannel也可以容纳其它的图形元素,但一般看不见Pannel,Pannel不能作为应用程序的独立窗口显示出来,Pannel要想显示出来就必须得把自己装入到Window里面才能显示出来。

    • Frame
      Frame是Windows的子类,由Frame或其子类创建的对象,为一个窗体
      构造方法:public Frame()构造一个最初不可见的 Frame 新实例
      public Frame(String title)构造一个新的、最初不可见的、具有指定标题的 Frame 对象
      成员方法
      public void setBounds(int x, int y, int width, int height)设置窗体位置和大小,x,y是左上角坐标,width和height是宽度和高度
      public void setSize(int width, int height)设置窗体的大小
      public void setLocation(int x, int y)设置窗体的位置
      public void setBackground(Color c)设置背景颜色,参数为Color对象
      public void setVisible(boolean b)设置窗体是否可见,默认为不可见
      public void setTitle(String title)设置Frame的标题
      public String getTitle()获得Frame的标题
      public void setResizable(boolean resizable)设置是否可以调整大小
      Frame代码实例:
    public class MyTest {
    public static void main(String[] args) {
    	//这里只是在内存里面创建了一个窗口对象 还不能真正显示出来让我们看到
        Frame frame = new Frame("JAVA图形界面窗口");
    
    	//设置窗体的背景颜色
        frame.setBackground(Color.blue);
    
    	//设置窗体是否可见
        //要想看到在内存里面创建出来的窗口对象
        //必须调用setVisble()方法
        //并且把参数true传入才能看得见窗体
        //如果传入的参数是false
        //那么窗体也是看不见的
        frame.setVisible(true);
    
    	//设置窗体的初始大小
        frame.setSize(500,500);
    
    	//设置窗体出现时的位置,如果不设置则默认在左上角(0,0)位置显示
        frame.setLocation(200,200);
    
    	// 设置窗体能否被改变大小
        // 设置为false后表示不能改变窗体的显示大小
        // 这里将窗体显示的大小设置为200X200
        // 那么窗体的显示只能是这个大小了,不能再使用鼠标拖大或者缩小
        frame.setResizable(false);
    
    	//设置窗体在点击右上角的“X”按钮时可以退出程序
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }}
    
    • Panel
      Panel对象可以看成容纳Component的空间,且可以拥有自己的布局管理器,并且拥有从父类继承来的方法
      构造方法:public Panel()使用默认的布局管理器创建新面板
      public Panel(LayoutManager layout)构造一个新的、最初不可见的、具有指定标题的 Frame 对象
      成员方法
      public void setBounds(int x, int y, int width, int height)设置面板位置和大小,x,y是左上角坐标,width和height是宽度和高度
      public void setSize(int width, int height)设置面板的大小
      public void setLocation(int x, int y)设置面板的位置
      public void setBackground(Color c)设置背景颜色,参数为Color对象
      public void setLayout(LayoutManager mgr)设置面板的布局管理器
      Panel代码实例:
public class TestPanel {
    public static void main(String[] args) {
        Frame frame = new Frame("JAVA Frame With Panel");
        Panel panel = new Panel(null);
        frame.setLayout(null);

        //这里设置的坐标(300,300)是相对于整个屏幕的
        frame.setBounds(300,300,500,500);

        //设置背景颜色时使用三基色(红,绿,蓝)的比例来调配背景色
        frame.setBackground(new Color(0,0,102));

        //这里设置的坐标(50,50)是相对于Frame窗体的
        panel.setBounds(50,50,400,400);
        panel.setBackground(new Color(204,204,255));

        //把Panel容器装入到Frame容器中,使其能在Frame窗口中显示出来
        frame.add(panel);

        frame.setVisible(true);

        //解决关闭问题
        frame.addWindowListener(new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {

            }

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

            @Override
            public void windowClosed(WindowEvent e) {

            }

            @Override
            public void windowIconified(WindowEvent e) {

            }

            @Override
            public void windowDeiconified(WindowEvent e) {

            }

            @Override
            public void windowActivated(WindowEvent e) {

            }

            @Override
            public void windowDeactivated(WindowEvent e) {

            }
        });
    }
}
  • LayoutManger(布局管理器)
    Java中,提供了布局管理器类的对象可以管理,管理Component在Container中的布局,不必直接设置Component位置和大小,且每个Container都有一个布局管理器对象,当容器需要对某个组件进行定位或判断大小尺寸时,就会调用其对应的布局管理器,调用Container的setLayout方法改变其布局管理器对象。

    • FlowLayout(流式布局)
      FlowLayout是Panel类的默认布局管理器,具有如下特点:

      • FlowLayout布局管理器对组件进行定位,行内从左到右,一行排满后换行。
      • 不改变组件的大小,按组件原有尺寸显示组件,可设置不同的组件间距,行距以及对齐方式。
      • 默认的对齐方式是居中。

      构造方法:public FlowLayout()使用默认的居中对齐方式,水平和垂直间距为默认值(5)
      public FlowLayout(int align)使用指定的对齐方式,align的值必须为:FlowLayout.LEFT、FlowLayout.RIGHT、FlowLayout.CENTER、FlowLayout.LEADING 或 FlowLayout.TRAILING
      public FlowLayout(int align, int hgap, int vgap)使用指定的对齐方式以及水平和垂直间距,align的值必须为:FlowLayout.LEFT、FlowLayout.RIGHT、FlowLayout.CENTER、FlowLayout.LEADING 或 FlowLayout.TRAILING
      FlowLayout代码实例:

    public class TestFlowLayout {
    public static void main(String[] args) {
        Frame frame = new Frame("FlowLayout");
    
        //使用Button类创建按钮
        // 按钮类的其中一个构造方法:Button(String label) label为按钮显示的文本
        Button button1 = new Button("button1");
        Button button2 = new Button("button2");
        Button button3 = new Button("button3");
    
        // setLayout方法的定义:public void setLayout(LayoutManager mgr)
        // 使用流水(Flow)线般的布局
        frame.setLayout(new FlowLayout());
        // 使用了布局管理器FlowLayout,这里的布局采用默认的水平居中模式
    
        // frame.setLayout(new FlowLayout(FlowLayout.LEFT));
        // 这里在布局的时候使用了FlowLayout.LEFT常量,这样就将按钮设置为左对齐
    
        // frame.setLayout(new FlowLayout(FlowLayout.RIGHT));
        //这里在布局的时候使用了FlowLayout.RIGHT常量,这样就将按钮设置为右对齐
    
    
        frame.setSize(200,200);
    
        frame.add(button1); // 把创建出来的按钮放置到Frame窗体中
        frame.add(button2); // 这里并没有设置按钮的大小与位置
        frame.add(button3); // 设置按钮的大小与位置都是由布局管理器来做的
        
        frame.setVisible(true);
     }
    }
    
    • BorderLayout(边框布局)
      BorderLayout是Frame类的默认布局管理器,具有如下特点:

      • BorderLayout布局管理器将整个容器划分成:东(EAST)、西(WEST)、南(SOUTH)、北(NORTH)、中(CENTER)五个区域,组件只能添加到指定的区域。
      • 如果不指定组件的加入部位,则默认加入到CENTER区。
      • 每个区域只能加入一个组件,若加入多个,则先前加入的会被覆盖。

      构造方法:public BorderLayout()构造一个组件之间没有间距的新边框布局
      public BorderLayout(int hgap, int vgap)构造一个具有指定组件间距的边框布局
      BorderLayout代码实例:

    public class TestBorderLayout {
    public static void main(String[] args) {
        Frame frame = new Frame("TestBorderLayout");
    
        Button buttonEast = new Button("East");
        Button buttonWest = new Button("West");
        Button buttonSouth = new Button("South");
        Button buttonNorth = new Button("North");
        Button buttonCenter = new Button("Center");
    
        //把按钮放置到Frame窗体时按照东西南北中五个方向排列好,推荐使用这种方式去排列窗体元素
        //这样容易检查出错误 因为这样写如果写错了编译器会提示出错
    
        frame.add(buttonEast,BorderLayout.EAST);
        frame.add(buttonWest,BorderLayout.WEST);
        frame.add(buttonSouth,BorderLayout.SOUTH);
        frame.add(buttonNorth,BorderLayout.NORTH);
        frame.add(buttonCenter,BorderLayout.CENTER);
    
        //也可以使用这样的方式排列按钮 在把按钮放置到Frame窗体时使用方向定位的字符串指定按钮的放置位置
        //这种使用方向定位的字符串指定按钮的放置方式不推荐使用 一旦写错了方向字符串就不好检查出来
        //因为即使是写错了仍然可以编译通过
        /*
        frame.add(buttonEast,"EAST");
        frame.add(buttonWest,"West");
        frame.add(buttonSouth,"South");
        frame.add(buttonNorth,"North");
        frame.add(buttonCenter,"Center");
        */
    
        frame.setSize(200,200);
        frame.setVisible(true);
      }
    }
    
    • GridLayout(表格布局)
      GridLayout型布局管理器将空间划分成规则的矩形网络,每个单元格区域大小相等。组件被添加到每个单元格中,先从左到右填满一行后换行,再从上到下。
      构造方法:public GridLayout()创建具有默认值的表格布局,即每个组件占据一行一列
      public GridLayout(int rows, int cols)创建具有指定行数和列数的表格布局
      GridLayout代码实例:
    public class TestGridLayout {
    public static void main(String[] args) {
        Frame frame = new Frame("TestGridLayout");
    
        Button btn1 = new Button("btn1");
        Button btn2 = new Button("btn2");
        Button btn3 = new Button("btn3");
        Button btn4 = new Button("btn4");
        Button btn5 = new Button("btn5");
        Button btn6 = new Button("bnt6");
    
        // 把布局划分成3行2列的表格布局形式
        frame.setLayout(new GridLayout(3,2));
    
        frame.add(btn1);
        frame.add(btn2);
        frame.add(btn3);
        frame.add(btn4);
        frame.add(btn5);
        frame.add(btn6);
    
        // Frame.pack()是JAVA语言的一个函数
        // 这个函数的作用就是根据窗口里面的布局及组件的preferredSize来确定frame的最佳大小。
        frame.pack();
        frame.setVisible(true);
    	}
    }
    
    • 布局嵌套
      这几种布局管理器可以设置在Frame里面,也可以设置在Panel里面,而Panel本身也可以加入到Frame里面,因此通过Frame与Panel的嵌套就可以实现比较复杂的布局。
      代码如下:
    public class TestTenButtons {
    public static void main(String[] args) {
        //这里主要是对显示窗体进行设置
        Frame frame = new Frame("布局管理器的嵌套使用");
    
        //把整个窗体分成2行1列的表格布局
        frame.setLayout(new GridLayout(2,1));
    
        frame.setLocation(300,400);
        frame.setSize(400,300);
        frame.setVisible(true);
        frame.setBackground(new Color(204,204,255));
    
        //这里主要是对Panel进行布局的设置
        Panel p1 = new Panel(new BorderLayout());
        //p2使用2行1列的表格布局
        Panel p2 = new Panel(new GridLayout(2,1));
        Panel p3 = new Panel(new BorderLayout());
        //p4使用2行2列的表格布局
        Panel p4 = new Panel(new GridLayout(2,2));
    
        //这里主要是把按钮元素加入到Panel里面
        p1.add(new Button("East(p1-东)"),BorderLayout.EAST);
        p1.add(new Button("West(p1-西)"),BorderLayout.WEST);
    
        p2.add(new Button("p2-Button1"));
        p2.add(new Button("p2-Button2"));
    
        //p1里面嵌套p2,把p2里面的按钮作为p的中间部分装入到p1里面
        //把p2作为元素加入到p1里面
        p1.add(p2,BorderLayout.CENTER);
    
        p3.add(new Button("East(p3-东)"),BorderLayout.EAST);
        p3.add(new Button("West(p3-西)"),BorderLayout.WEST);
    
        for(int i=0;i<4;i++){
            p4.add(new Button("p4-Button"+i));
        }
    
        //p3里面嵌套p4,把p4里面的按钮作为p的中间部分装入到p3里面
        p3.add(p4,BorderLayout.CENTER);
    
        //把Panel装入Frame里面,以便于在Frame窗体中显示出来
        frame.add(p1);
        frame.add(p3);
    	}
    }
    

    效果如下:
    在这里插入图片描述

  • Component(组件)
    Component,即可以实现各种功能的特殊组件。

    • Button(按钮)
      这里主要介绍按钮监听器的使用方法
      原理图如下:
      在这里插入图片描述
      代码示例如下:
    public class TestActionEvent {
    public static void main(String[] args) {
        Frame frame = new Frame("TestActionEvent");
    
        Button button = new Button("Press Me");
        // 创建一个监听对象
        MyActionListener listener = new MyActionListener();
    
        // 把监听加入到按钮里面,监听按钮的动作,
        // 当按钮触发打击事件时,就会返回一个监听对象e
        // 然后就会自动执行actionPerformed方法
        button.addActionListener(listener);
    
        frame.add(button, BorderLayout.CENTER);
        frame.pack();
    
        addWindowClosingEvent(frame);
    
        frame.setVisible(true);
    
    }
    
    //点击窗体上的关闭按钮关闭窗体
    
    private static void addWindowClosingEvent(Frame frame){
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
    }
    
    // 自定义Monitor(监听)类实现事件监听接口ActionListener
    // 一个类要想成为监听类,那么必须实现ActionListener接口
    class MyActionListener implements ActionListener{
    
    //重写ActionListener接口里面的actionPerformed(ActionEvent e)方法
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("A Button has been Pressed");
     }
    }
    
    • TextField(文本编辑框)
      这里主要介绍文本监听器的使用方法
      原理图如下:
      在这里插入图片描述
      代码示例如下:
    public class TestTextField {
    public static void main(String[] args) {
        new MyFrameTextField();
    }
    }
    
    class MyFrameTextField extends Frame{
    MyFrameTextField(){
        TextField textField = new TextField();
        add(textField);
        textField.addActionListener(new MyMonitor2());
    
        //这个setEchoChar()方法是设置文本框输入时显示的字符,这里设置为*,
        //这样输入任何内容就都以*显示出来,不过打印出来时依然可以看到输入的内容
        textField.setEchoChar('*');
        setVisible(true);
        pack();
    }
    }
    
    class MyMonitor2 implements ActionListener{
    
    //接口里面的所有方法都是public(公共的)
    //所以从API文档复制void actionPerformed(ActionEvent e)时 要在void前面加上public
    @Override
    public void actionPerformed(ActionEvent e) {
        //事件的相关信息都封装在了对象e里面,通过对象e的相关方法就可以获取事件的相关信息
    
        //getSource()方法是拿到事件源,注意:拿到这个事件源的时候
        //是把它当作TextField的父类来对待
        //getSource()方法的定义是:“public Object getSource()”返回值是一个Object对象
        //所以要强制转换成TextField类型的对象
        //在一个类里面想访问另外一个类的事件源对象可以通过getSource()方法
        TextField textField = (TextField) e.getSource();
    
        // textField.getText()是取得文本框里面的内容
        System.out.println(textField.getText());
    
        // 把文本框里面的内容清空
        textField.setText("");
    }
    }
    
    • paint(绘图方法)
      每个Component都有一个paint(Graphics g)用于实现绘图目的,每次重画该Component时都自动调用paint方法
      代码示例如下:
public class TestPaint {
    public static void main(String[] args) {
        new MyPaint().launchFrame();
        //在main()方法里面并没有显示调用paint(Graphics g)方法
        //可是当创建出Frame窗体后却可以看到Frame窗体上画出了圆和矩形
        //这是因为paint()方法是一个比较特殊的方法
        //在创建Frame窗体时会自动隐式调用
        //当我们把Frame窗体最小化又再次打开时
        //又会再次调用paint()方法重新把圆和矩形在Frame窗体上画出来
        //即每次需要重画Frame窗体的时候就会自动调用paint()方法
    }
}

class MyPaint extends Frame{
    public void launchFrame(){
        setBounds(200,200,640,480);
        setVisible(true);
    }

    public void paint(Graphics g){
        //paint(Graphics g)方法有一个Graphics类型的参数g
        //我们可以把这个g当作是一个画家,这个画家手里拿着一只画笔
        //我们通过设置画笔的颜色与形状来画出我们想要的各种各样的图像

        /*设置画笔的颜色*/
        g.setColor(Color.red);
        g.fillOval(100,100,100,100);/*画一个实心椭圆*/
        g.setColor(Color.green);
        g.fillRect(150,200,200,200);/*画一个实心矩形*/

        //这下面的两行代码是为了写程序的良好编程习惯而写的
        //前面设置了画笔的颜色,现在就应该把画笔的初始颜色恢复过来
        //就相当于是画家用完画笔之后把画笔上的颜色清理掉一样
        Color c = g.getColor();
        g.setColor(c);

        System.out.println("gogoogo");

    }

}

猜你喜欢

转载自blog.csdn.net/qq_41151659/article/details/90607570
今日推荐