GUI
Graphical Vser Interface(图形用户接口)。
用图形的形式来显示计算机操作界面,这样更方便直观
Java为GUI提供的对象都存在java.Awt和 javax.Swing包中
java.Awt:AbstractWindow Toolkit(抽象窗口工具包)
需要调用本地系统方法实现功能,属重量级控件。
javax.Swing:在Awt的基础上,建立的一套图形化界面系统。
其中提供了更多的组件,而且完全由Java实现,增强了一致性,属轻量级控件。
Awt中继承关系图
布局管理器
布局:容器中的组件的排放方式。
常见的布局管理器
1. FlowLayout(流式布局管理器)
从左到右顺序排列。是Panel默认的布局管理器
2. BorderLayout(边界布局管理器)
东南西北中的排列方式。Frame默认的布局管理器。如果只有一个组件,将会覆盖整个窗体。
3. GridLayout(网格布局管理器)
规矩的矩阵
4. CardLayout(卡片布局管理器)
选项卡
5. GridBagLayout(网格包布局管理器)
非规矩的矩阵
创建图形化界面步骤
1. 创建fame窗体
例:Frame f = new Frame(“我的窗口”); //可设置标题,就是窗口的名字
创建的窗体是不可见的,下面会学习如何让窗口变得可见。
2. 对窗体进行基本设置
可以用Frame类中的以下几种方法,不是全部方法,只是我会演示的方法
a. void setSize(int width , int height)
调整组件大小,宽为width,长为height
b. void setLocation(int x , int y)
将组建移动到指定位置。
c. void setBounds(int x , int y , int width , int heigth)
移动组建,并调整其大小。
d. voidsetLayout(LayoutManager mgr)
设置容器的布局管理。参数位置传入布局管理器的对象。
3. 定义组件
例:Button b =new Button(“我的按钮”); //定义组件对象,可设置组件的名称。
4. 将组建通过窗体的add方式添加到窗体中。
例:f.add(b); //将刚刚定义的按钮组建添加到窗体中。
5. 让窗体显示
void setVisible(boolean b) 使窗体可见
例:f.setVisible(true)
代码示例
/* 创建图形化界面演示代码 步骤 1.创建frame窗体 2.对窗体进行基本设置 3.定义组件 4.将组建通过窗体的add方法添加到窗体中 5.让窗体显示。 */ import java.awt.*; class AwtDemo { public static void main(String[] args) { //定义Frame对象,并在参数位置传入窗体名 Frame f = new Frame("我是一个小窗体"); //定义窗体大小 f.setSize(300,200); //设置窗体的位置 f.setLocation(400,500); //指定布局管理器 f.setLayout(new FlowLayout()); //定义一个按钮组件,并在参数中传入组件名称 Button b = new Button("按我啊~"); //将组建添加到窗体中 f.add(b); //让窗体显示 f.setVisible(true); } }
运行结果
虽然我们创建了这个窗口,但是有一点小小的问题,就是窗体右上角的X点了不能结束,只能是我在DOS命令行中使用ctrl+c 结束程序。
窗体现在是无法提供正常使用的。要想让窗体和窗体内的组件可以具备功能,就要使用到我们下面要学习的,事件监听机制。
事件监听机制
事件监听机制的组成
事件源(组件)
事件(Event)
监听器(Listener)
事件处理
事件监听机制流程图
事件监听机制特点
1. 事件源:就是awt包和swing包中的那些图形界面组件
2. 事件:每个事件源都有自己特有的对应事件和共性事件。
3. 监听器:将可以触发某一个事件的动作(不只一个动作)都封装在监听器中。
以上三者在java中都已定义好,直接获取其对象来用即可。
我们要做的事情是对产生的动作进行处理。
4. 事件处理
现在我们要使用窗口上的X来关闭窗口。但是我刚才试过了,不行。
这时可以使用 java.awt.window类中的方法
void addWindowListener(WindowLIstener L) 添加指定的窗口监听器,以窗口接收窗口事件。
但是呢,这个方法接受的参数类型WindowListener是一个接口类型的参数,创建子类对象只能复写其中所有的方法,
但是我们只用到了一个关闭窗口方法。所以这时就要使用WindowAdapter类,它是WindowListener的子类已经实现了该接口。
并覆盖了其中所有的方法,那么只要继承WindowAdapter类,并覆盖所需的方法即可。
要再定义一个类什么的写继承太麻烦了,所以就用匿名内部类内部类的知识来完成。(WindowAdapter适配器,方便功能使用)
例:f.addWindowListener(new WindowAdapter() {
要监听的动作方法;
});
WindowAdapter中的部分方法展示
1. void windowClosing(WindowEvent e) 窗口正处于关闭过程中调用
2. void windowActivated(WindowEvext e) 激活窗口时调用。
3. void windowOpend(WindowEvent e) 一打开窗口时调用。
其中WindowEvent为事件对象。
理解:这些方法可以用于在操作窗口时执行指定的代码块。
如:windowActivated方法可以用于记录窗口被激活的次数,每次窗口被激活调用次数+1.
windowOpend方法中可以输出语句,输出如何使用窗体的说明等等。
就用我刚才创建的窗体的例子,我们来使X管用。
/* 事件监听处理方法演示 监听事件源,当用户对事件源做出监听器正在监听的动作后进行处理 在窗体已经建立完的情况下 思路: 给事件源添加监听器 将适配器作为参数传入构造函数中 使用内部类的方式定义事件发生之后的处理方式 */ import java.awt.*; import java.awt.event.*; class AwtDemo2 { public static void main(String[] args) { //定义Frame对象,并在参数位置传入窗体名 Frame f = new Frame("我是一个小窗体"); //定义窗体大小 f.setSize(300,200); //设置窗体的位置 f.setLocation(400,500); //指定布局管理器 f.setLayout(new FlowLayout()); //定义一个按钮组件,并在参数中传入组件名称 Button b = new Button("按我啊~"); //将组建添加到窗体中 f.add(b); //为窗体添加监听器,将适配器作为参数传入构造函数中,定义内部类 f.addWindowListener(new WindowAdapter() { //复写WindowAdapter类中的方法,创建自己的事件处理方式 //点X可以关闭窗口,并输出语句 public void windowClosing(WindowEvent e) { //输出语句 System.out.println("我走了再见"); //程序结束 System.exit(0); } //激活窗口时显示被激活 public void windowActivated(WindowEvent e) { System.out.println("我被你激活了!"); } //窗口一建立就输出信息 public void windowOpened(WindowEvent e) { System.out.println("嗨,小伙伴"); } }); //让窗体显示 f.setVisible(true); } }
运行结果
按钮事件
在我们上面做的窗口中还有个按钮,下面我们来学习按钮的事件处理
按钮就是事件源, 那么选择哪个监听器呢?
通过前一个示例了解到,要想知道哪个组件具备什么样的特有监听器,要去查看该组件对象的功能。
在API中我们找到了Buttom类中的方法
void addActionListener(ActionListener l) 添加指定的动作监听器,以接收发自此按钮的动作事件。
因为addActionListener方法参数ActionListener类中,只有一个void actionPerformed(ActionEvent e)方法,
它的功能也就是我们需要的,发生操作时调用。所以使用匿名内部类,直接复写这个方法即可即可。
(这是少有的没有适配器的接口)
下面来看代码演示
/* 事件监听小程序 需求 按窗体X关闭窗体 按按钮也退出窗体 */ import java.awt.*; import java.awt.event.*; class AwtDemo3 { //定义该图形中所需的组件的引用。 private Frame f; private Button but; //对象一建立就调用init方法。 AwtDemo3() { init(); } public void init() { //建立窗体对象,并传入字符串作为窗体名 f = new Frame("我是一个小窗体~"); //对frame进行基本设置。 //设置窗体的长宽,还有位置 f.setBounds(400,200,300,500); //设置窗体使用哪个布局 f.setLayout(new FlowLayout()); //建立按钮对象,并传入字符串作为按钮上现实的信息 but = new Button("我是按钮~"); //将组件添加到窗体中 f.add(but); //加载一下窗体上事件。 myEvent(); //显示窗体; f.setVisible(true); } //设置窗体事件方法。 private void myEvent() { //给窗体添加监听器,WindowAdapter是窗口监听器的子类 f.addWindowListener(new WindowAdapter() { //窗体一建立就输出信息 public void windowOpened(WindowEvent e) { System.out.println("我来啦~"); } //窗体关闭时输出信息,并结束程序 public void windowClosing(WindowEvent e) { System.out.println("我走了"); System.exit(0); } }); //给按钮添加监听器 but.addActionListener(new ActionListener() { //按按钮 退出窗体 public void actionPerformed(ActionEvent e) { System.out.println("退出,按钮干的"); System.exit(0); } }); } public static void main(String[] args) { new AwtDemo3(); } }
运行结果
鼠标事件
鼠标有三个监听器
void addMouseListener(MouseListener l)
添加指定的鼠标侦听器,以接收发自此组件的鼠标事件。
void addMouseMotionListener(MouseMotionListener l)
添加指定的鼠标移动侦听器,以接收发自此组件的鼠标移动事件。
void addMouseWheelListener(MouseWheelListener l)
添加指定的鼠标滚轮侦听器,以接收发自此组件的鼠标滚轮事件。
当我们为按钮设定鼠标监听器之后要复写事件处理方法,传入的参数是事件对象。
事件对象中也有方法,可以调用。如:我们如果给鼠标添加第一个监视器,复写方法
void mouseClicked(MouseEvent e) 鼠标按键在组件上单击(按下并释放)时调用。
可以在按钮被鼠标点的时候调用此方法,来完成事件处理。其中参数MouseEvent对象中还有方法可以供我们使用。
如int getClickCount() 返回与此事件关联的鼠标单击次数。返回我点了几次按钮。
所以想要通过此事件做更多的事情,要去事件对象中寻找。
注意:按钮的自己被按事件和鼠标去点击按钮时间,鼠标事件会先执行。
键盘事件
void addKeyListener(KeyListener l)
添加指定的按键侦听器,以接收发自此组件的按键事件。
同样的,和鼠标监听一样,想要使用特殊的方法就去找事件对象中的方法。
练习
/* 图形化界面练习 需求 输入一个目录,列出目录下的所有文件,如果传入的目录错误,则出现弹框提示 思路 1.创建窗体 2.添加组件,文本框,文本区,按钮 3.创建弹窗,指定它的所有者是哪个窗体,并起名字 4.添加组件,标签,按钮 5.给窗体文本框添加监听器,使输完数据按回车时可以展示出目录中的文件 6.给窗体按钮添加监听器,使一按按钮就可以展示目录中文件 7.给窗体添加监听器,一按X就退出 8.给弹窗的窗体和按钮添加监听器,使一按按钮或者按X,弹窗就消失 9.使窗体显示。 10.获取目录下所有文件,如果传入的目录错误,则把错误信息显示在弹窗上,并使弹窗显示 这个是个挺长的程序啊 大家准备好,注释我就不写那么详细了,简单的就不写啦~ */ import java.awt.*; import java.awt.event.*; import java.io.*; class WindowDemo { //创建要使用的组件的引用 //窗口的 private Frame f; private TextField tf; private Button b1; private TextArea ta; //对话框的 private Dialog dia; private Label l; private Button b2; //对象一建立就调用init方法 WindowDemo() { init(); } public void init() { //建立窗体对象,设置属性,添加组件 f = new Frame("我是一个可以列出所有文件的窗体"); f.setBounds(300,100,600,500); f.setLayout(new FlowLayout()); tf = new TextField(60); b1 = new Button("转到"); ta = new TextArea(25,70); f.add(tf); f.add(b1); f.add(ta); //建立对话框属相,设置属性,添加组件 dia = new Dialog(f,"看我看我",true); dia.setBounds(400,200,240,150); dia.setLayout(new FlowLayout()); l = new Label(); b2 = new Button("知道啦"); dia.add(l); dia.add(b2); //调用添加监听器方法 myEvent(); //使窗体显示 f.setVisible(true); } //添加监听器方法 private void myEvent() { //先给对话框添加监视器,使按X和按按钮都消失 b2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dia.setVisible(false); } }); dia.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dia.setVisible(false); } }); //给文本框添加监听器 tf.addKeyListener(new KeyAdapter() { //在文本框内用键盘输入信息时 public void keyPressed(KeyEvent e) { //如果按了ender键,也就是回车键 if(e.getKeyCode()==KeyEvent.VK_ENTER) //调用展示目录内所有文件的方法 showDir(); } }); //给按钮添加监听器 b1.addActionListener(new ActionListener() { //如果按钮被按了 public void actionPerformed(ActionEvent e) { //就调用展示目录内所有文件的方法 showDir(); } }); //给窗体添加监听器 f.addWindowListener(new WindowAdapter() { //窗体被按X public void windowClosing(WindowEvent e) { //程序退出 System.exit(0); } }); } //展示目录内所有文件的方法 private void showDir() { //获取文本框中输入的信息,也就是目录 String dirPath = tf.getText(); //将目录封装成对象 File dir = new File(dirPath); //如果这个目录是一个文件或者是一个文件夹 if(dir.exists() && dir.isDirectory()) { //则先往把文本区清空 ta.setText(""); //获取文件夹中所有文件或文件夹名称的数组 String[] names = dir.list(); //遍历数组 for(String name : names) { //将名称添加到文本区中 ta.append(name+"\r\n"); } } //如果输入的数据不是目录也不是文件 else { //定义一个要输出的字符串 String info = "您输入的信息:"+dirPath+"有误。查查再输入"; //添加到对话框的标签中 l.setText(info); //使对话框显示 dia.setVisible(true); } } public static void main(String[] args) { new WindowDemo(); } }
运行结果
菜单
菜单的继承关系
Menu:菜单,继承MenuItem;有右三角的图标存在,可添加Menu和MenuItem
MenuBar:菜单栏,可添加菜单和菜单条目。一般先创建菜单栏,再创建菜单。
MenuItem:菜单条目,也称菜单项,无右三角的图标存在,是最终的菜单项。
菜单的事件处理和组件一样,可以对类型为MenuItem和Menu的对象事件源添加活动监听ActionListener,并进行相关的事件处理。
通过setMenuBar()方法,将菜单添加到Frame中。
打开文件
要用到Dialog对话框的子类FileDialog
构造函数
FileDialog(Frame parent , String title , int made)
made为对话模式,可以是FileDialog.LOAD打开。FileDialog.SAVE保存。不写默认为LOAD。
结合菜单,演示代码。
package myPack /* 建立菜单,并通过菜单打开文件。 我有在上面创建一个包,为了接下来的jar包调用用的,稍安勿躁等会儿讲~ */ import java.awt.*; import java.awt.event.*; import java.io.*; public class MyMenuTest { //建立组建的引用 private Frame f; private MenuBar bar; private TextArea ta; private Menu fileMenu; private MenuItem openItem,saveItem,closeItem; //打开和保存文件用的组件 private FileDialog openDia,saveDia; //File对象的引用 private File file; MyMenuTest() { init(); } public void init() { //建立窗体并设置属性 f = new Frame("小窗口"); f.setBounds(300,100,650,600); //建立菜单栏 bar = new MenuBar(); //建立文本框,用于展示打开的文件 ta = new TextArea(); //建立文件菜单 fileMenu = new Menu("文件"); //建立打开,保存,退出三个菜单项 openItem = new MenuItem("打开"); saveItem = new MenuItem("保存"); closeItem = new MenuItem("退出"); //把三个菜单项添加到文件菜单中 fileMenu.add(openItem); fileMenu.add(saveItem); fileMenu.add(closeItem); //将文件菜单添加到菜单栏中 bar.add(fileMenu); //将菜单栏组件添加到窗体中 f.setMenuBar(bar); //打开文件和保存文件组件,属于f窗体 openDia = new FileDialog(f,"我要打开",FileDialog.LOAD); saveDia = new FileDialog(f,"我要保存",FileDialog.SAVE); //在窗体中添加文本框组件 f.add(ta); //设置我的事件 myEvent(); //使窗体显示 f.setVisible(true); } //设置事件方法 private void myEvent() { //给保存菜单项添加监听器 saveItem.addActionListener(new ActionListener() { //当保存菜单项被点了 public void actionPerformed(ActionEvent e) { //判断file指向的对象是否存在 if(file==null) { //显示保存组件 saveDia.setVisible(true); //获取此文件对话框的目录 String dirPath = saveDia.getDirectory(); //获取此文件对话框的选定文件。 String fileName = saveDia.getFile(); if(dirPath==null || fileName==null) return ; //将获取的目录和文件名封装成对象 file = new File(dirPath,fileName); } //异常处理 try { //写入文件 BufferedWriter bufw = new BufferedWriter(new FileWriter(file)); //获取文本框中的文字 String text = ta.getText(); //将文字写入输出流中 bufw.write(text); bufw.flush(); bufw.close(); } catch (IOException ex) { throw new RuntimeException(); } } }); //给打开菜单项添加监视器 openItem.addActionListener(new ActionListener() { //当打开菜单项被点的时候 public void actionPerformed(ActionEvent e) { //打开文件组件显示 openDia.setVisible(true); //获取被选中文件的目录 String dirPath = openDia.getDirectory(); //获取被选中文件的文件名 String fileName = openDia.getFile(); if(dirPath==null || fileName==null) return ; //清空文本区 ta.setText(""); //将获取的目录和文件名封装成对象 file = new File(dirPath,fileName); try { //创建输入流 BufferedReader bufr = new BufferedReader(new FileReader(file)); //读取文件中的内容 String line = null; while((line=bufr.readLine())!=null) { ta.append(line+"\r\n"); } bufr.close(); } catch (IOException ex) { throw new RuntimeException("读取失败"); } } }); //给关闭菜单项添加监视器 closeItem.addActionListener(new ActionListener() { //当关闭菜单项被点 public void actionPerformed(ActionEvent e) { //程序结束 System.exit(0); } }); //窗体被点X程序结束 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } public static void main(String[] args) { new MyMenuTest(); } }
运行结果
Jar包
既然是图形化界面,就需要通过图形化界面的形式运行程序,而不是是用Dos命令行执行,
那么如何通过双击程序就执行程序呢?这就需要将程序的class文件打包。
步骤如下:
1. 首先要在java文件中导入一个包,没有则需创建一个包,如package mypack;
2. 生成包:通过编译javac -d e:\myclass MyMenuTest.java,此时则在e盘下的myclass文件夹下生成了所有的.class文件
3. 在此目录下新建一个文件,如1.txt或者其他任意名称任意扩展名的文件都可,
然后在其中编辑固定的格式:“Main-Class: mymenu.MenuDemo”,只写引号中的内容。需要在冒号后有一个空格,在文件末尾要回车。
4. 编译:jar -cvfm my.jar 1.txt mypack即可。如果想添加其他信息,则直接编译jar即可得出相应的命令
5. 此时双击即可执行。