1. 事件处理:
在Java中事件以具体的对象来表示,使用者的相关动作会由JVM建立相对应的事件,用以描述事件来源、发生了什么事情以及相关的消息,需要通过捕捉对应的事件,以进行对应的操作来完成应用程序的功能。
2. Java事件模型:
Java对事件的处理采用委托事件模型(Delegation Event Model),在这个模型下,事件被送到对应的组件,而组件会将事件传播至每个事件监听器(Event Listener),事件监听器中定义了与不同事件相对应的事件处理者(Event Handler),只有向组件注册的事件监听器才能收到事件。通过这种模型,事件发生时是委托事件处理者进行处理,事件处理者与组件的设计可以分别独立。
具体来说,事件监听器实现了java.util.EventListener接口,不过这个接口只是个标示接口(Marker Interface)。其中并没有规定必须实现的方法。对于J2SE窗口程序而言,相对应的事件监听器主要位于java.awt.event与javax.swing.event包之下,它们都是EventListener的子接口。
3. 文字编辑器的事件处理:
以菜单项被单击时的事件处理来说,要实现java.awt.event.ActionListener接口。例如:
//打开"文件"菜单项的事件处理
menuOpen.addActionListener
{
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
openFile();
}
}
}
这时采取的是匿名类的方式实现了ActionListener接口,该接口定义了actionPerformed()方法,这个方法就是事件处理者。 您要在当中实现菜单项被单击时所要进行的处理。当菜单项被单击时会发出ActionEvent。这个事件会传递给曾向菜单项组件注册的事件监听器,并调用对应的事件处理者。向菜单项组件注册事件监听器的方式是使用addActionListener()方法。
以上示范的是JMenuItem的事件处理,至于JTextArea的事件方面,由于需求中主要是针对编辑文字时的事件作处理,编辑文字主要是键盘操作,因而会发生KeyEvent事件。可以实现java.awt.event.KeyListener接口来设置相关的事件处理,这个接口有3个方法(事件处理者)必须实现:
package ysu.hxy;
public interface KeyListener
{
public void keyPressed(KeyEvent e)
public void keyReleased(KeyEvent e)
public void keyTyped(KeyEvent e)
}
对于这个将要制作的文字编辑器而言,您所感兴趣的主要是键盘被按下进行文字编辑时的事件处理,所以可以仅实现keyTyped()方法,另两个方法在实现时保持空白即可,也可以继承java.awt.event.KeyAdapter。KeyAdapter类实现KeyListener接口,而对3个方法实现时仅保持空白,通过继承KeyAdapter,可以用仅重新定义keyTyped()方法,而不用对另两个方法也进行实现,编写时较为方便且程序代码看来也会比较简洁。可以使用JTextArea的addKeyListener()方法加入事件监听器,例如:
//编辑区键盘事件
textArea.addKeyListener(
new KeyAdapter()
{
public void keyTyped(KeyEvent e)
{
processTextArea();
}
}
);
文字编辑区也会有鼠标事件,也就是使用鼠标按右键显示快捷菜单,以执行剪切、复制、粘贴的动作来进行文字编辑。鼠标事件监听器是实现java.awt.event.MouseListener接口,其中有5个方法必须实现,如果觉得麻烦,可以继承java.awt.event.MouseAdapter,它实现了MouseListener接口,但实现方法时保持空白,也可以在继承MouseAdapter后,对感兴趣的事件处理者进行实现。例如:
//编辑区鼠标事件
textArea.addMouseListener
{
new MouseAdapter()
{
public void mouseReleased(MouseEvent e)
{
if(e.getButton() == MouseEvent.BUTTON3)
popUpMenu.show(editMenu,e.getX(),e.getY());
}
public void mouseClicked(MouseEvent e)
{
if(e.getButton() == MouseEvent.BUTTON1)
popUpMenu.setVisible(false);
}
}
}
鼠标处理者接受的是MouseEvent,您可以使用getButton()方法取得一个常数,表示按下的是那个鼠标键,MouseEvent.Button1是指按下鼠标左键,MouseEvent.Button3表示按下鼠标右键,您使用JTextArea的addMouseListener()方法加入监听器。程序片段中的popUpMenu参考至javax.swing.JPopupMenu的实例,这个实例可用编辑菜单直接取得。例如:
JPopupMenu popUpMenu = editMenu.getPopupMenu();
还有一个事件是您要处理的,就是单击窗口右上角的X按钮时,希望动作与单击菜单中“关闭”具有相同的行为,所以删去原来程序中的这行:
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
并且改为自行实现java.awt.event.WindowListener。这个接口中有7个方法必须实现,如果觉得麻烦,可以继承实现了此接口的java.awt.event.WindowAdapter。然后对感兴趣的方法进行实现。例如:
//单击窗口关闭按钮事件处理
addWindowListener(
new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
closeFile();
}
}
);
要向JFrame注册WindowListener,可以使用addWindowListener()方法。windowClosing()方法会在单击X按钮后,窗口真正关闭前执行。 以下是将以上说明实际套用至文字编辑器实现中的程序代码:
package ysu.hxy;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
//import java.awt.event.InputEvent;
//import java.awt.event.KeyEvent;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.JPopupMenu;
import javax.swing. JOptionPane;
public class JNotePadUI extends JFrame
{
private JMenuItem menuOpen;
private JMenuItem menuSave;
private JMenuItem menuSaveAs;
private JMenuItem menuClose;
private JMenu editMenu;
private JMenuItem menuCut;
private JMenuItem menuPaste;
private JMenuItem menuCopy;
private JMenuItem menuAbout;
private JTextArea textArea;
private JPopupMenu popUpMenu;
public JNotePadUI()
{
super("新建文本文件");
setUpUIComponent();
setUpEventListener();
setVisible(true);
}
private void setUpUIComponent()
{
setSize(640,480);
//菜单栏
JMenuBar menuBar = new JMenuBar();
//设置"文件"菜单
JMenu fileMenu = new JMenu("文件");
menuOpen = new JMenuItem("打开");
//快捷键设置
menuOpen.setAccelerator(
KeyStroke.getKeyStroke(KeyEvent.VK_O,InputEvent.CTRL_MASK));
menuSave = new JMenuItem("保存");
menuSave.setAccelerator(
KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK));
menuSaveAs = new JMenuItem("另存为");
menuClose = new JMenuItem("关闭");
menuClose.setAccelerator(
KeyStroke.getKeyStroke(KeyEvent.VK_Q,InputEvent.CTRL_MASK));
fileMenu.add(menuOpen);
//添加分隔线
fileMenu.addSeparator();
fileMenu.add(menuSave);
fileMenu.add(menuSaveAs);
//添加分隔线
fileMenu.addSeparator();
fileMenu.add(menuClose);
//设置"编辑"菜单
JMenu editMenu = new JMenu("编辑");
menuCut = new JMenuItem("剪切");
menuCut.setAccelerator(
KeyStroke.getKeyStroke(KeyEvent.VK_X,
InputEvent.CTRL_MASK));
menuCopy = new JMenuItem("复制");
menuCopy.setAccelerator(
KeyStroke.getKeyStroke(KeyEvent.VK_C,
InputEvent.CTRL_MASK));
menuPaste = new JMenuItem("粘贴");
menuCopy.setAccelerator(
KeyStroke.getKeyStroke(KeyEvent.VK_V,
InputEvent.CTRL_MASK));
editMenu.add(menuCut);
editMenu.add(menuCopy);
editMenu.add(menuPaste);
//设置"关于"菜单
JMenu aboutMenu = new JMenu("关于");
menuAbout = new JMenuItem("关于JNotePad");
aboutMenu.add(menuAbout);
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(aboutMenu);
//设置菜单栏
setJMenuBar(menuBar);
//文字编辑区域
textArea = new JTextArea();
textArea.setFont(new Font("宋体",Font.PLAIN,16));
textArea.setLineWrap(true);
JScrollPane panel = new JScrollPane(textArea,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
Container contentPane = getContentPane();
contentPane.add(panel,BorderLayout.CENTER);
//状态栏
JLabel stateBar = new JLabel("未修改");
stateBar.setHorizontalAlignment(SwingConstants.LEFT);
stateBar.setBorder(BorderFactory.createEtchedBorder());
contentPane.add(stateBar,BorderLayout.SOUTH);
popUpMenu = editMenu.getPopupMenu();
}
private void setUpEventListener() {
// 按下窗口关闭钮事件处理
addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
closeFile();
}
}
);
// 菜单 - 打开
menuOpen.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
openFile();
}
}
);
// 菜单 - 保存
menuSave.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveFile();
}
}
);
// 菜单 - 另存为
menuSaveAs.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveFileAs();
}
}
);
// 菜单 - 关闭文件
menuClose.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
closeFile();
}
}
);
// 菜单 - 剪切
menuCut.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
cut();
}
}
);
// 菜单 - 复制
menuCopy.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
copy();
}
}
);
// 菜单 - 粘贴
menuPaste.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
paste();
}
}
);
// 菜单 - 关于
menuAbout.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 显示对话框
JOptionPane.showOptionDialog(null,
"程序名称:\n JNotePad \n" +
"程序设计:\n 良葛格\n" +
"简介:\n 一个简单的文字编辑器\n" +
" 可作为验收Java的实现对象\n" +
" 欢迎网友下载研究交流\n\n" +
"http://caterpillar.onlyfun.net/",
"关于JNotePad",
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null, null, null);
}
}
);
// 编辑区键盘事件
textArea.addKeyListener(
new KeyAdapter() {
public void keyTyped(KeyEvent e) {
processTextArea();
}
}
);
// 编辑区鼠标事件
textArea.addMouseListener(
new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON3)
popUpMenu.show(editMenu, e.getX(), e.getY());
}
public void mouseClicked(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1)
popUpMenu.setVisible(false);
}
}
);
}
private void openFile(){}
private void saveFile(){}
private void saveFileAs(){}
private void closeFile(){}
private void cut(){}
private void copy(){}
private void paste(){}
private void processTextArea(){}
public static void main(String[] args)
{
new JNotePadUI();
}
}