《Head First Java 2nd Edition》 摘录
JFrame 代表屏幕上的一个窗口,可以把 buttons, checkboxes, test fields 等等界面相关的东西置于其上。它可以有一个有菜单项的菜单条。无论在哪个平台上,都有窗口图标,最小化、最大化和关闭窗口的按钮。
JFrame 在不同平台上的外观是不一样的。
可以把 javax.swing 包下的许多部件添加到 JFrame 中,最常用的控件是:
- JButton
- JRadioButton
- JCheckBox
- JLabel
- JList
- JScrollPane
- JSlider
- JTextArea
- JTextField
- JTable
大多数都易于使用,只有某些比较复杂(例如 JTable)。
创建一个GUI非常简单
第一步:新建一个JFrame
JFrame frame = new JFrame();
第二步:新建一个小部件
JButton button = new JButton("点击我呀");
第三步:把小部件添加到JFrame 中
frame.getContentPane().add(button);
第四步:显示窗体
frame.setSize(300, 300);
frame.setVisible(true);
一个最简GUI示例
package ch12;import javax.swing.*;import java.awt.event.*; // 监听事件public class SimpleGUI01 implements ActionListener{JButton button;int count = 0;public static void main(String[] args) {SimpleGUI01 gui = new SimpleGUI01();gui.go();}public void go(){JFrame frame = new JFrame("最简GUI");button= new JButton("点击我呀");// 添加事件监听器才能响应事件button.addActionListener(this);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.getContentPane().add(button); // 从这里把 JButton 添加到 JFrameframe.setSize(300, 300);frame.setVisible(true); // 这一步是必须的,不然看到GUI }@Overridepublic void actionPerformed(ActionEvent e) {count ++;button.setText("点击我了" + count);}}
响应事件
单击按钮如何让按钮响应事件?
我们需要准备两样东西:
- 一个method,特殊事件发生时调用它,比如单击按钮
- 一个方式,让我们知道何时会触发上面的方法
得到用户事件
想像一下,你希望单击按钮之后按钮上的文字由click me变成I've been clicked,首先我们可以写一个方法来改变按钮的文字:
public void changeIt(){button.setText("I've been clicked!");
}
但是,现在怎么办?我们怎么知道按钮何时被单击了。
在 Java 中,获取和处理用户事件的过程被称作 event-handling,在Java中有许多不同的事件类型,几乎绝大部分和GUI用户动作相关。如果用户单击按钮,这就是一个事件。这个事件表明用户期望的按钮的事件发生了。如果这是一个Slow Tempo按钮,用户期望slow tempo事件发生。如果是聊天客户端上的发送按钮,用户期望的发送我的消息的事件发生了。所以最直截了当的事件是用户单击按钮,表明他们期望一个动作发生。
对于按钮,你通常都不会考虑中间状态,例如按钮按下了或者按钮释放了。你对按钮的期望是:不管用户是怎么单击、双击按钮的,不管鼠标按住了多长时间,不管用户在释放按钮之前想法发生了什么变化,仅仅通知我用户是何时发生了动作。
1、按钮需要知道我们代码关注它的状态
2、当事件发生时按钮需要以某种方式告知我们
以上两个问题的解决办法就是 listener interface,它是一座沟通listener(你)和 event source(按钮)的桥梁。
Swing GUI 组件都是event sources (事件源),在Java语言中,事件源就是一个能把用户动作(单击鼠标,敲击按键,关闭窗口)转变成事件的对象。就像在Java语言中事实上所有的事物都可以用对象来代表。是某种event class的对象。如果你浏览API中的java.awt.event包,可以看见许许多多的事件类(显而易见,它们的名字中都有Event)。你可以看到MouseEvent, KeyEvent, WindowEvent, ActionEvent 还有许许多多的。
当用户做出某种动作的时候,source(事件源,比如按钮)就会创建一个event object(事件对象)。你的绝大部分代码都是接收事件而不是创建事件。换一句话说,你花费几乎所有的时间都在作为一个事件监听器(event listener),而不是事件源(event source)。
每一个事件类型都有与之对应的监听器接口(listener interface)。如果你期待MouseEvent,就实现MouseListener interface。期待WindowEvents,就实现 WindowListener。明白了否?另外需要谨记实现接口的规则:实现一个你要声明实现的接口,就需要实现这个接口里面所有的方法。
有的接口有不止一个方法,因为这个接口有多重作用。举例说明,如果你要实现MouseListener,你就要实现mousePressed, mouseReleased, mouseMoved 等等。尽管它们都来自 MouseEvent,但它们有不同的实现方法。如果你实现MouseListener,当用户按下鼠标的时候会调用方法mousePressed()。当用户释放鼠标的时候,会调用mouseReleased()方法。对于鼠标事件,只有一个事件对象 MouseEvent,但是对于不同的鼠标事件类型,会调用不同的方法。
监听器和事件源是如何沟通的
Listener
如果你的类想要知道按钮的 ActionEvents,就需要实现 ActionListener 接口。按钮也需要知道你对它感兴趣,你需要在按钮上注册,在按钮上调用 addActionListener(this) 并且传递 ActionListener 引用给它(在当前情况下,你是 ActionListener,所以可以通过 this 传递)。按钮需要在事件发生的时候以某个方式通知你,所以它调用监听器接口的方法。作为一个监听器,你必须要实现这个接口的唯一的一个方法 actionPerformed()。
Event Source
按钮是 ActionEvents 的事件源,所以它必须知道哪一个对象是感兴趣的监听者。按钮有一个方法 addActionListener() ,可以把感兴趣的监听者作为参数传递给这个按钮。当按钮的 addActioinListener() 方法运行时,它会把参数存到一个列表中。当用户点击按钮时,按钮在列表中的每一个监听器上调用 actionPerformed() 方法发出这个事件。
3种添加事物到GUI的方法
- 添加小部件到 JFrame 上
frame.getContentPane().add(myButton);
- 在小部件上绘画 2D 图形
graphics.fillOval(70, 70, 100, 100);
- 在小部件上显示图片
graphics.drawImage(myPic, 10, 10, this);
创建自己的绘图小部件
可以设置小部件,移动,动画,改变颜色等等属性。
默认情况下,一个frame有5个区域留给你添加小部件。