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. 此时双击即可执行。