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 执行.
*/
原文地址:https://www.cnblogs.com/yiqiu2324/p/3175882.html