众所周知,Java的GUI并不做的精彩,人家都说Java的代码都是一处编译到处运行,但是这个GUI却是一处编译到处调试。所以我们并不会使用它。这里为了GUI方面的知识不是完全的空白,就简单的过一下,这里写下一些总结。
如何创建一个窗口并显示
Graphical User Interface(图形用户接口)
public static void main(String[] args) {
Frame f = new Frame("my window");
f.setLayout(new FlowLayout());//设置布局管理器
f.setSize(500, 400);//设置窗体大小
f.setLocation(300, 200);//设置窗体出现在屏幕的位置
f.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png"));//设置icon图标
f.setVisible(true);//设置为可视的
}
此时我们点击 窗口上的X 是没有反应的,我们需要给它写监听事件。
布局管理器
FlowLayout(流式布局管理器)
从左到右的顺序排列
Panel默认的布局管理器
BorderLayout(边界布局管理器)
东,南,西,北,中
Frame默认的布局管理器
由于我这里直接添加(默认中),相当于填充所以按钮占了整一个窗口。
GridLayout(网格布局管理器)
规则的矩阵,这个比较好理解,就不截图了,就像矩阵一样
CardLayout(卡片布局管理器)
选项卡,下面这样,我们点一个显示一个这样。
GridBagLayout(网格包布局管理器)
非规则的矩阵
打开你电脑上的计算器,那个就是一个应用。非规则的矩阵
事件监听
窗体监听
public static void main(String[] args) {
Frame f = new Frame("我的窗体");
f.setSize(100, 100);
f.setVisible(true);//可视化
//事件源是窗体,把监听器注册到事件源上
//事件对象(WindowEvent)传递给监听器
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0); //退出虚拟机,关闭窗口
}
});
}
现在,你就可以关闭你的窗口了。
你可能会有疑惑,addWindowListener方法不是应该添加WindowListener,而现在为什么在里面new 一个WindowAdapter(适配器)呢?
我们可以查看API发现WindowListener是一个接口,我数了一下,里面有7个方法(关闭,打开,最小化...),那么意味着我们必须实现这七个方法才可创建对象。
我们再来查看下WindowAdapter的源码
public abstract class WindowAdapter
implements WindowListener, WindowStateListener, WindowFocusListener
{
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
//此处省略几个空方法
}
我们可以发现,他也实现了WindowListener接口,但是里面的方法都是空的,而且该对象是abstract的,所以我们不能直接创建这个类对象(因为你创建了对象调用的都是空方法也没有意义),那么我们可以定义一个类去继承他(上面代码我用了匿名创建),而需要什么就重写什么,这样我们就方便多了,所以我们上面的功能只需关闭,所以我们直接重写了windowClosing这一个方法就ok了,而要是你实现WindowListener,你必须实现七个方法,而其他六个都是没有用的,看如下代码
f.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
});
所以可见适配器的重要性了(但是如果你每个方法都需使用那就另当别论了)
除了窗体监听外还有鼠标监听,键盘监听,动作监听,我就不详细说明了(看下面代码),其都有对应的适配器类(动作监听无,其内只有一个方法)。
对于动作监听,可能看名字不太能看出来是什么?这里我们举一个例子,你使用某播放器播放视频时,你会发现,你敲下一个空格或者鼠标单击,其视频都会暂停。所以动作监听其默认指向的就是键盘空格和鼠标单击
public static void main(String[] args) {
Frame f = new Frame("我的第一个窗口");
f.setSize(400,600);
f.setLocation(500, 50);
f.setIconImage(Toolkit.getDefaultToolkit().createImage("qq.png"));
Button b1 = new Button("按钮一");
Button b2 = new Button("按钮二");
f.add(b1);
f.add(b2);
f.setLayout(new FlowLayout()); //设置布局管理器
f.setVisible(true);//必须设置可视,默认不可视
//添加窗体监听
f.addWindowListener(new WindowAdapter() {
@Override//窗口关闭
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//为按钮一添加鼠标监听
b1.addMouseListener(new MouseAdapter() {
@Override//鼠标单击
public void mouseClicked(MouseEvent e) {
System.exit(0);
}
@Override//鼠标释放
public void mouseReleased(MouseEvent e) {
System.exit(0);
}
});
//为按钮一添加键盘监听
b1.addKeyListener(new KeyAdapter() {
@Override//键盘释放
public void keyReleased(KeyEvent e) {
//这里你可以输出你按下的那个键所对应的值(每个键都对应唯一的值)
System.out.println(e.getKeyCode());
//查看KeyEventAPI,你会发现有大量的静态常量字段,便于我们使用(我们不可能记住每个键的code)
if(e.getKeyCode() == KeyEvent.VK_SPACE) { //这里VK_SPACE 代表空格键
System.exit(0);
}
}
});
//为按钮二添加动作监听(可发现该接口只有1个方法)
b2.addActionListener(new ActionListener() {
@Override//你无论是敲空格键还是鼠标左键,都会退出Jvm
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
适配器
上面讲到了适配器,那么上面是适配器可能又有点糊涂,这里涉及到了一个设计模式(适配器设计模式)
什么是适配器
在使用监听器的时候, 需要定义一个类事件监听器接口,通常接口中有多个方法, 而程序中不一定所有的都用到, 但又必须重写, 这很繁琐.
适配器简化了这些操作, 我们定义监听器时只要继承适配器, 然后重写需要的方法即可.
适配器原理
适配器就是一个类, 实现了监听器接口, 所有抽象方法都重写了, 但是方法全是空的。适配器类需要定义成抽象的,因为创建该类对象,调用空方法是没有意义的
目的就是为了简化程序员的操作, 定义监听器时继承适配器, 只重写需要的方法就可以了.
下面我们使用一个例子来深刻了解下什么是适配器。
我们假设做一个和尚都需要打坐,念经,敲钟,练武,还有一堆的门规等等,那么和尚也是有例外的,比如鲁智深就习武,还有济公它应该啥事都不干吧,拿唐僧来讲,他不会习武,如果和尚是一个接口,那么我们要是创建这些鲁智深,唐僧这些类该怎么创建呢?看完下面代码你就会了。
注:以下代码为了便于理解使用中文。正常开发情况不要使用
//适配器设计模式
interface 和尚 {
public void 打坐();
public void 念经();
public void 撞钟();
public void 习武();
}
//声明成抽象的原因是,不想让其他类创建本类对象,因为创建也没有意义,方法都是空的
abstract class 天罡星 implements 和尚 {
@Override
public void 打坐() {
}
@Override
public void 念经() {
}
@Override
public void 撞钟() {
}
@Override
public void 习武() {
}
}
class 鲁智深 extends 天罡星 {
public void 习武() {
System.out.println("倒拔垂杨柳");
System.out.println("拳打镇关西");
System.out.println("大闹野猪林");
System.out.println("......");
}
}
看如果是创建鲁智深对象,那么可以只需重写一个方法即可。切记开发中不能用中文。
事件处理
事件: 用户的一个操作
事件源: 被操作的组件
监听器: 一个自定义类的对象, 实现了监听器接口, 包含事件处理方法,把监听器添加在事件源上, 当事件发生的时候虚拟机就会自动调用监听器中的事件处理方法
这里拿我们上面点击按钮退出虚拟机来说。
点击就是事件,而事件源就是那个被点击的按钮,我们需要定义一个监听器(上面我们使用了适配器),重写了里面的mouseClicked方法(system.exit(0)),并添加(addMouseListener)到按钮上。当我们点击了按钮时,java虚拟机便会自动帮我们调用监听器中的处理方法(mouseClicked方法),执行完代码(system.exit(0))就退出了虚拟机。
好了,GUI的东西不必深入,这里就当了解下就ok了!