zoukankan      html  css  js  c++  java
  • day22_GUI(组件,事件监听机制,双击jar包执行)

    1.GUI概述:

    /*
    GUI:Graphical User Interface(图形用户接口)
     两种和用户交互的界面:命令行和图形化界面(便于用户操作)
    Java为GUI提供的对象都存在Java.Awt和Javax.Swing
    
    java.Awt:Abstract Window ToolKit(抽象窗口工具包)
     需要调用本地系统方法实现功能.(依赖于平台,跨平台不是太好)
     属重量级控件.
    javax.Swing:在AWT的基础上,建立的一套图形界面系统,其中提供了更多的组件
    而且完全由Java实现.增强了移植性,属轻量级控件.
    
    eclipse使用独立的Xwt开发界面
    */

    2.组件体系(常用):

    Component体系

    3.布局管理器:

    /*
    <示意图>
    容器中的组件的排放方式,就是布局
    常见的布局管理器:
       1.FlowLayout(流式布局管理器)
         从左到右的顺序排列
         Panel默认的布局管理器
       2.BorderLayout(边界布局管理器)
         东 南 西 北 中
         Frame默认的布局管理器
       3.GardLayout(网格布局管理器)
         规则矩阵
       4.CardLayout(卡片布局管理器)
         选项卡
       5.GridBagLayout(网格包布局管理器)
         非规则矩阵
    */

    布局管理器

    4.窗体+按钮简单示例:

    4

    package awtdemo;
    import java.awt.Frame;
    import java.awt.Button;
    import java.awt.FlowLayout;
    class AwtDemo{
     public static void main(String[] args){
        Frame frame=new Frame("MiniAwt");// 构造一个新的、最初不可见的、具有指定标题的 Frame 对象。
        frame.setVisible(true);//设置该窗口可见
        frame.setSize(500,400);//分别代表横坐标与纵坐标,设置大小,单位像素
        frame.setLocation(100,100);//设置窗体最初的位置
        
        Button b=new Button("我是一个按钮");
        frame.add(b);//把按钮添加到窗体中
        frame.setLayout(new FlowLayout());//由于frame默认(BorderLayout)边界式布局,没有设置东南西北导致
                                          //该按钮填充整个窗体,改变为流式布局
        
        System.out.println("Hello");//打印完Hello,程序没有结束,说明主线程执行完,还有其它线程没有执行完
                                    //也就是说图形化界面工作在一个独立的线程中(可以从任务管理器中看出)
     }
    }
    /*
    创建图形化界面基本思想:
     1.创建Frame窗体
     2.对窗体进行基本设置
       比如大小,位置,布局
     3.定义组件
     4.将组件通过窗体的add方法添加到窗体中
     5.让窗体显示,setVisible(true);
    */

    注意到点击X没反应:

     窗口 按钮

    5.事件监听机制(类似于异常的检测与捕获)

    /*
    (示意图)
    事件监听机制特点:
    1.事件源
    2.事件
    3.监听器
    4.事件处理
    
    事件源:就是awt包或者swing包中的那些图形界面组件
    
    事件:每一个事件源都有自己特有的对应事件和共性事件(windows窗体都有被鼠标/键盘操作)
    
    监听器:将可以触发某一个事件后相应 动作(方法声明) (不止一个)都已经封装到了监听器中
    
    以上三者,在java中都已经定义好了.直接获取其对象来用就可以
    
    关键就是对产生动作进行处理(方法具体实现)
    */

    事件监听机制

    代码示例:

    package awtdemo;
    import java.awt.Frame;
    import java.awt.Button;
    import java.awt.FlowLayout;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    class AwtDemo2{
     public static void main(String[] args){
        Frame frame=new Frame("Mini");
    
        
        frame.setSize(500,400);
        frame.setLocation(100,100);
        
        //Button b=new Button("我是一个按钮");
        //frame.add(b);
        frame.setLayout(new FlowLayout());
     
        
        /*将监听器注册到Frame上*/    
         frame.addWindowListener(new MyWin());//需要传入一个监听器对象
         /*
         分析下大致流程:
         把new MyWin()监听器注册到frame上->监听器监听的 点击X动作 作用于frame->
         封装成关闭窗口事件对象->传递给new MyWin监听器中的we,执行处理动作
                                 即public void windowClosing(WindowEvent we)
         特别类似 异常检测与捕获
         */
            
        //frame.setVisible(true);    //当该语句放到这个位置,会有"Mini打开"输出,很费解
         
         frame.addWindowListener(new WindowAdapter(){//匿名内部类
            public void windowActivated(WindowEvent we){
              System.out.println("Mini置顶");
            
            }
             public void windowOpened(WindowEvent we){
              System.out.println("Mini打开"); 
            }
         
         });
        frame.setVisible(true);//注册完监听,打开窗口动作才能捕捉到
     }
    }
    
    /*如何创建监听器对象呢??*/
    //方式一:
    //class MyWin implements WindowListener{
     /*
     必须把7个方法全实现了才能new MyWin()
     而我只需要用一个方法,显得非常麻烦 
     */
    
    //}
    //方式二:
    //WindowListener的子类WindowAdapter已经实现了windowListenter接口
    //所有方法(方法体均为空,创建对象没有意义,因此其为abstract)
    //那么只需要extends WindowAdapter,复写需要使用的方法即可
    class MyWin extends WindowAdapter{
      public void windowClosing(WindowEvent we){
        //System.out.println("window closing "+we.toString());//看下事件对象中封装那些信息
        
        /*
        window closing sun.awt.TimedWindowEvent[WINDOW_CLOSING,opposite=null,oldState=0,
        newState=0] on frame0
        */
        
         
        System.exit(0);//结束程序,使图形界面工作的线程也结束,实现关闭窗体
      }
    
    }

    把以上代码简单优化下:

    package awtdemo;
    import java.awt.Frame;
    import java.awt.Button;
    import java.awt.FlowLayout;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    class FrameDemo{
     private Frame frame;
     private Button but;
     FrameDemo(){
       initi();
     
     }
     /*执行初始化动作*/
     private void initi(){
       frame=new Frame("MyFrame");
       frame.setBounds(200,200,500,300);//void setBounds(int x, int y, int width, int height)  
       frame.setLayout(new FlowLayout());
       but=new Button("窗体按钮");
       frame.add(but);
       listenerReg();
       frame.setVisible(true);
     }
     /*将监听注册到组件上*/
     private void listenerReg(){
       frame.addWindowListener(new WindowAdapter(){
         public void windowClosing(WindowEvent we){
           System.out.println("点击X关闭");
           System.exit(0);
         }
       });
       
       but.addActionListener(new ActionListener(){//该接口就一个方法,没有适配器
          public void actionPerformed(ActionEvent ae){
           System.out.println("点击按钮关闭");
           System.exit(0);
          }
       });
     }
     public static void main(String[] args){
       new FrameDemo();
    
     }
    }
    /*
    规律:
    监听器注册到组件上:addxxxListener()
    监听器对象:如果监听器中监听动作很少,建议使用:xxxListener
               否则,根据需要:xxxAdapter
    */

    6.鼠标键盘监听和鼠标键盘事件

    package awtdemo;
    import java.awt.Frame;
    import java.awt.Button;
    import java.awt.FlowLayout;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.TextField;
    class MouseAndKey{
     private Frame frame;
     private Button but;
     private TextField tf;
     MouseAndKey(){
       initi();
     
     }
     /*执行初始化动作*/
     private void initi(){
       frame=new Frame("MyFrame");
       frame.setBounds(200,200,500,300);//void setBounds(int x, int y, int width, int height)  
       frame.setLayout(new FlowLayout());
       tf=new TextField(20);//单行文本框,制定列宽为20
       but=new Button("窗体按钮");
       frame.add(tf);
       frame.add(but);
       listenerReg();
       frame.setVisible(true);
     }
     /*将窗口监听注册到组件上*/
     private void listenerReg(){
       frame.addWindowListener(new WindowAdapter(){
         public void windowClosing(WindowEvent we){
           System.out.println("点击X关闭");
           System.exit(0);
         }
       });
       but.addActionListener(new ActionListener(){
          public void actionPerformed(ActionEvent ae){
            System.out.println("该按钮活动");//会先执行"鼠标单击按钮并释放",
                                             //再执行"该按钮活动",因为鼠标单击先于按钮活动触发
                                             
          }
       }); 
       /*将鼠标监听注册到按钮上,鼠标动作引发事件属于共性事件*/
       but.addMouseListener(new MouseAdapter(){
         int enterCount=1;
         int clickCount=1;
         public void mouseClicked(MouseEvent me){
         
          System.out.println("鼠标单击按钮并释放"+clickCount++);
           /*想判断是否双击,MouseEvent内部封装了具体动作引发的事件等描述该事件的具体属性或信息*/
          System.out.println(me.getClickCount());
         
    if(me.getClickCount()==2)
    {//其实相当于 单击释放 该动作在较短时间间隔连续执行了两次
                                      //返回与此事件关联的鼠标单击次数
           System.out.println("双击了");
          }
          
         }
         public void mouseEntered(MouseEvent me){
          // System.out.println("鼠标经过按钮"+enterCount++);  
         }   
         
       });
    
      /*将键盘监听器注册到按钮上*/
      but.addKeyListener(new KeyAdapter(){//运行可以看到按钮上有个虚线框,说明其为当前事件源,键盘按键动作用于该按钮,引发事件
       public void keyPressed(KeyEvent ke){
        System.out.println(KeyEvent.getKeyText(ke.getKeyCode())+"..."+ke.getKeyChar());
         if((KeyEvent.getKeyText(ke.getKeyCode())).equals("Esc"))//按下Esc关闭窗体
            System.exit(0); 
         if(ke.isControlDown()&&(KeyEvent.getKeyText(ke.getKeyCode())).equals("Enter"))//按下Ctrl+Enter关闭窗体(组合键)
            System.exit(0);
        }
      }
      );
      
      /*实现只能在文本框输入数字,屏蔽字符*/
      tf.addKeyListener(new KeyAdapter(){
        public void keyPressed(KeyEvent ke){
         if(ke.getKeyCode()<'0'||ke.getKeyCode()>'9'){
            System.out.println(ke.getKeyChar()+"非法");
            ke.consume();
            /*
             InputEvent中的consume方法描述:
              使用此事件,以便不会按照默认的方式由产生此事件的源代码来处理此事件。
              按照默认的方式由产生此事件的源代码来处理此事件:在这里是指让键盘敲入的
                                                             值进入文本框
            */
         }
        
        }
      
      });
     }
     public static void main(String[] args){
       new MouseAndKey();
    
     }
    }

    7.点击按钮列出目录下的文件:

    /*
    在文本框中输入目录,点击转到按钮,将该目录中的文件与文件夹
    名称列在下面的文本区域中
    在这里的事件源为按钮.
    */
    package listdir;
    import java.awt.Frame;
    import java.awt.Button;
    import java.awt.TextField;
    import java.awt.TextArea;
    import java.awt.FlowLayout;
    import java.awt.Dialog;
    import java.awt.Label;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.io.File;
    class ListDir{
     private Frame frame;
     private Button fraBut;
     private TextField tf;
     private TextArea ta;
     private File file;
     
     private Dialog dia;//添加错误提示对话框
     private Label la;//不能直接添加文本,可通过添加标签实现
     private Button diaBut;
     
     public ListDir(){
       initi(); 
     }
     public void initi(){
      
      frame=new Frame();
      frame.setBounds(200,200,500,300);
      fraBut=new Button("转到");
      tf=new TextField(30);
     
      
      frame.setLayout(new FlowLayout());
      frame.add(tf);
      frame.add(fraBut);
      ta=new TextArea(10,40);//指定文本区为五行四十列
      frame.add(ta);
      
      fraListenerReg();
      
      frame.setVisible(true);
     }
     private void fraListenerReg(){
         
        frame.addWindowListener(new WindowAdapter(){
           public void windowClosing(WindowEvent we){
              System.exit(0); 
           }
         });
         
         
         /*点击按钮列出指定目录*/
         fraBut.addActionListener(new ActionListener(){//不使用MouseListener,因为可能用户使用键盘
           public void actionPerformed(ActionEvent ae){
                listDir();
            }
         });
         /*按回车列出制定目录*/
         tf.addKeyListener(new KeyAdapter(){
           public void keyPressed(KeyEvent ke){
             if(ke.getKeyCode()==KeyEvent.VK_ENTER)  
              listDir();
           }
         });
        
        
     }
      /*把目录列出单独封装到函数中,便于重复使用*/
         public void listDir(){
                file=new File(tf.getText());//获取文本框文本(制定路径)
                
    if(file.exists()&&file.isDirectory()){//
    判断该路径指定的目录是否存在并且是否是目录
               
    ta.setText("");//清空掉上次的显示
                        for(String f : file.list()) 
                         ta.append(f+"
    ");
                }
                else{
                 dia=new Dialog(frame,"目录出错",true);//注意dialog也是窗体一种,不要添加到Frame中
                                            //如果为modal为true,当对话框显示时,不能操作其它窗体
                  dia.setLayout(new FlowLayout());//对话框内部布局方式也为边界式布局
                  dia.setBounds(400,400,400,150);
                 la=new Label(file.toString()+"无效路径");
                 diaBut=new Button("确定");
                 dia.add(la); 
                 dia.add(diaBut);
                 
                 diaListenerReg();
                 
                 dia.setVisible(true);
                }
         
         
         }
     /*把注册到对话上的监听单独封装*/
     public void diaListenerReg(){
         
              /*将窗体监听注册到对话框上*/
            dia.addWindowListener(new WindowAdapter(){
               public void windowClosing(WindowEvent we){
                  dia.setVisible(false);//隐藏对话框
               }
             });
             /*将窗体监听注册到diaBut上*/
             diaBut.addActionListener(new ActionListener(){
               public void actionPerformed(ActionEvent we){
                  dia.setVisible(false);
               }
             });
         
         }
        
    public static void main(String[] args){
    
      new ListDir();
     }
    }

    点击按钮列出文件

    对话框

    8.MenuBar,Menu,MenuItem

    /*
     MenuBar(菜单栏),Menu,MenuItem
     Menu extends MenuItem
     菜单中可以有菜单项,菜单项可以是普通条目,也可以是菜单
    */
    package menu;
    import java.awt.MenuBar;
    import java.awt.Menu;
    import java.awt.MenuItem;
    import java.awt.Frame;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    class MenuDemo{
      private Frame frame;
      private MenuBar menuBar;
      private Menu menu,subMenu;
      private MenuItem menuItem,subItem;
      public MenuDemo(){
         initial();
      
      }
      public void initial(){
        frame=new Frame();
        frame.setBounds(300,300,500,400);
        menuBar=new MenuBar();
        menu=new Menu("文件");
        subMenu=new Menu("子菜单");
        menuItem=new MenuItem("退出");
        subItem=new MenuItem("子条目");
        
        menuBar.add(menu);//将菜单menu添加到菜单栏
        menu.add(subMenu);//在菜单menu中添加子菜单subMenu
        subMenu.add(subItem);//在子菜单中添加子条目
        menu.add(menuItem);//在菜单menu中添加菜单项menuItem
    
        frame.setMenuBar(menuBar);//将菜单栏添加到窗体中
         
        listenerReg();
        frame.setVisible(true);
      }
      public void listenerReg(){
        frame.addWindowListener(new WindowAdapter(){
          public void windowClosing(WindowEvent we){
             System.exit(0); 
          }
        });
        /*将活动监听注册到菜单menuItem上(可能使用键盘操作,因此不是鼠标监听)*/
        menuItem.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent ae){
             System.exit(0); 
         }
       });
      }
      
     public static void main(String[] args){
        new MenuDemo();
      
      }
    
    
    }

    菜单

    9.FileDialog应用:模拟打开/保存 对话框及其功能:

    /*
     需要用到对话框子类FileDialog
     注意其构造函数有两种mode:LOAD,SAVE
    */
    package menu;
    import java.awt.MenuBar;
    import java.awt.Menu;
    import java.awt.MenuItem;
    import java.awt.Frame;
    import java.awt.FileDialog;
    import java.awt.TextArea;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    import java.io.File;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    class MenuDemo{
      private Frame frame;
      private MenuBar menuBar;
      private Menu menu;
      private FileDialog fileDialog; 
      private MenuItem closeItem,openFileItem,saveFileItem;
      private TextArea textArea;
      private File file;
      public MenuDemo(){
         initial();
      
      }
      public void initial(){
        frame=new Frame();
        frame.setBounds(300,300,500,400);
        menuBar=new MenuBar();
        menu=new Menu("文件");
        textArea=new TextArea();//默认BorderLayout->使其填满整个窗口
        closeItem=new MenuItem("退出");
        openFileItem=new MenuItem("打开");
        saveFileItem=new MenuItem("保存");
        menuBar.add(menu);//将菜单menu添加到菜单栏
        
        menu.add(closeItem);//在菜单menu中添加菜单项menuItem
        menu.add(openFileItem);
        menu.add(saveFileItem);
    
        frame.setMenuBar(menuBar);//将菜单栏添加到窗体中
        frame.add(textArea);
    
        listenerReg();
        frame.setVisible(true);
      }
      public void listenerReg(){
        frame.addWindowListener(new WindowAdapter(){
          public void windowClosing(WindowEvent we){
             System.exit(0); 
          }
        });
        /*将活动监听注册到菜单menuItem上(可能使用键盘操作,因此不是鼠标监听)*/
        closeItem.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent ae){
             System.exit(0); 
         }
       });
        openFileItem.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent ae){
           fileDialog=new FileDialog(frame,"打开",FileDialog.LOAD);     
           fileDialog.setVisible(true);  
           loadFileToTextArea();
         }
       });
        saveFileItem.addActionListener(new ActionListener(){
           public void actionPerformed(ActionEvent ae){
            fileDialog=new FileDialog(frame,"保存",FileDialog.SAVE);
            String dirPath=null;
            String fileName=null;
           
    if(file==null){//
    对话框弹出之前,判断当前文件在硬盘是否存在
                          //存在,直接保存无需弹出对话框
             fileDialog.setVisible(true);
             
             dirPath=fileDialog.getDirectory();
             fileName=fileDialog.getFile();
             file=new File(dirPath,fileName);//文件不存在或没有被打开需要获取指定名称
            }
            if(fileName!=null)//未指定文件名称
              saveFile();       
           }
         });
      }
      
      public void loadFileToTextArea(){
           String dirPath=fileDialog.getDirectory();
           String fileName=fileDialog.getFile();
          
    if(fileName==null
    )//未指定文件
                return;
           file=new File(dirPath,fileName);//fileName为null,引发NullPointerException,因此在创建File对象前加上判断
           BufferedReader bfr=null;
           try{
           bfr=new BufferedReader(new FileReader(file));//读取为文本,因此FileReader
           String line=null; 
           textArea.setText("");//在添加前清空TextArea
           while((line=(bfr.readLine()))!=null)
              textArea.append(line+"
    ");
           }
           catch(IOException e){
            throw new RuntimeException("读取文件失败");
           }
           finally{
             if(bfr!=null)
                try{
                 bfr.close();
                }
                catch(IOException e){
                 throw new RuntimeException("关闭流失败");
                }
           }
      }
    public void saveFile(){
      BufferedWriter bfw=null;
      try{
        bfw=new BufferedWriter(new FileWriter(file));
        String text=textArea.getText();
        bfw.write(text);
        bfw.flush();
      }
      catch(IOException e){
        throw new RuntimeException("文件写入失败");
      }
      finally{
        if(bfw!=null)
          try{
           bfw.close();
          }
          catch(IOException e){
            throw new RuntimeException("关闭流失败");
          }
      }
    }
    public static void main(String[] args){
        new MenuDemo();
      
      }
    
    
    }

    文件对话框

    10.怎么把制作好的图形化界面双击打开?

    /*
    想要把自己做的简单菜单双击执行,而不用每次需要在命令行下
    执行.
    把生成的类->放在一个packag下(也可以不用,直接把几个类压缩)->压缩成jar包
    
    1.需要指定jar包中的含有main方法的类Main-Class
      通过一个文本文件写入:
      Main-Class: menu.MenuDemo
    
      注意:①Main-Class: 后必须有一个空格,不然在打包时引发:java.io.IOException: invalid header field
           ②menu.MenuDemo后有一个回车,虽然打包成功,但配置信息不能写入
    */

    jar

      jarIni.txt为配置信息:Main-Class: menu.MenuDemo

      jarIni.txt 必须跟在MyMenu.jar后面,而不能放在命令末尾,否则会出现FileNotFoundException 包名(拒绝访问) 格式问题

      menu:为需要压缩的package

    2.要想双击执行jar包,还需要进一步配置,在windows7/8下:

    具体可以参考:http://jingyan.baidu.com/article/200957617c3619cb0621b44d.html?tj=exp_relate_4&pu=sz@1320_2001&st=5&from=&ssid=&net_type=&bd_page_type=1&os=1&rst=

    /*
    2.在windows 7/8下配置注册表:
        其实打开图形化界面的程序通过JDK中的javaw.exe这个工具
       ①在注册表中找到该路径:
         HKEY_CLASSES_ROOTApplicationsjavaw.exeshellopencommand
       ② 
       默认值会根据自己的jre安装路径的不同而不同,只要在原来的数值中添加 -jar 即可
        比如我的是"C:Program FilesJavajdk1.7.0_21jreinjavaw.exe" "%1",
    修改数据数值为"C:Program FilesJavajdk1.7.0_21jreinjavaw.exe" -jar %1"
       (只要在原来的数值中添加 -jar 即可),这样就设置好了,jar文件就可以直接运行了。
       -jar两边有空格
    我们也可以直接在cmd命令行,进入当前要执行的.jar目录,然后使用javaw -jar xxx.jar 执行.
    */
  • 相关阅读:
    多线程案例龟兔赛跑
    不靠谱的事
    生命的价值并不止于自己的幸福
    我的高中搞笑班主任
    AgileChina参会笔记
    上美食
    程序中保留一个Dump
    骗子公司驾到
    我的《野蛮生长》书摘
    最近看的书的清单
  • 原文地址:https://www.cnblogs.com/yiqiu2324/p/3175882.html
Copyright © 2011-2022 走看看