1.GUI概述:
/* GUI:Graphical User Interface(图形用户接口) 两种和用户交互的界面:命令行和图形化界面(便于用户操作) Java为GUI提供的对象都存在Java.Awt和Javax.Swing java.Awt:Abstract Window ToolKit(抽象窗口工具包) 需要调用本地系统方法实现功能.(依赖于平台,跨平台不是太好) 属重量级控件. javax.Swing:在AWT的基础上,建立的一套图形界面系统,其中提供了更多的组件 而且完全由Java实现.增强了移植性,属轻量级控件. eclipse使用独立的Xwt开发界面 */
2.组件体系(常用):
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+"\r\n"); } 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+"\r\n"); } 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后有一个回车,虽然打包成功,但配置信息不能写入 */jarIni.txt为配置信息:Main-Class: menu.MenuDemo
jarIni.txt 必须跟在MyMenu.jar后面,而不能放在命令末尾,否则会出现FileNotFoundException 包名(拒绝访问) 格式问题
menu:为需要压缩的package
2.要想双击执行jar包,还需要进一步配置,在windows7/8下:
/* 2.在windows 7/8下配置注册表: 其实打开图形化界面的程序通过JDK中的javaw.exe这个工具 ①在注册表中找到该路径: HKEY_CLASSES_ROOT\Applications\javaw.exe\shell\open\command ② 默认值会根据自己的jre安装路径的不同而不同,只要在原来的数值中添加 -jar 即可 比如我的是"C:\Program Files\Java\jdk1.7.0_21\jre\bin\javaw.exe" "%1", 修改数据数值为"C:\Program Files\Java\jdk1.7.0_21\jre\bin\javaw.exe" -jar %1" (只要在原来的数值中添加 -jar 即可),这样就设置好了,jar文件就可以直接运行了。 -jar两边有空格
我们也可以直接在cmd命令行,进入当前要执行的.jar目录,然后使用javaw -jar xxx.jar 执行. */