• java_day09_GUI事件


    第九章:GUI事件

    1.AWT事件模型概述
    使用AWT或者Swing中的容器、组件和布局管理器就可以构建出图形界面,但是这时候该界面还并不能和用户进行交换,因为图形界面中的组件还没有添加事件监听器,所以还不能对用户在界面中的操作进行处理。

    在Java事件模型中,必须存在事件对象、事件源、事件监听器三部分。事件对象是表示发生了什么事件,事件源表示是谁产生的这个事件对象,事件处理器接收到事件对象后,可以对这个事件进行处理。
    事件模型中的三要素:事件对象、事件源、事件监听器
    注:不光是GUI中,在java的其他地方也会使用到事件模型。

    在Java中一个事件监听器就是指事件发生时被通知的对象。它有两个要求:首先,为了可以接收到特殊类型事件的通知,它必须在事件源中已经注册;其次,它必须实现接收和处理事件的方法。
    例如:
    //btn就是事件源
    JButton btn = new JButton("测试");
    //给事件源btn注册事件监听器
    //这里使用了匿名内部类对象作为监听器
    btn.addActionListener(new ActionListener() {
    //监听器中实现接收和处理事件的方法
    //ActionEvent类型的引用e指向的就是按钮上所产生的事件对象
    @Override
    public void actionPerformed(ActionEvent e) {
    System.out.println("hello");
    }
    });

    XxxxListener 监听器接口
    事件源.addXxxxListener(new XxxxListener(){
    //实现接口中的抽象方法
    });

    在事件源上注册好监听器之后,只要是在该事件源上产生了特定的事件对象,事件监听器就会自动被触发,并执行相应的方法处理。
    例如:在上面的例子基础上
    当我们使用鼠标点击btn这个按钮之后,产生了一个鼠标点击的事件对象(引用e会指向这个事件对象),然后注册的事件监听器会自动触发(这里的匿名内部类对象就是注册的监听器),并调用指定方法actionPerformed,对产生的事件进行处理。

    2.事件源、事件对象、事件监听器
    1)事件源
    AWT和Swing中的几乎所有的组件都可以作为事件源,注意容器也是一种组件。
    例如:窗口、面板、按钮、输入框、下拉类别的菜单、单选复选框、标签、滚动条、进度条等等

    例如:AWT和Swing中的组件都是java.awt.Component类的子类型,Component类中定义了很多所有组件都可以调用的方法,这些方法中有很多是这种形式的:addXxxxListener
    这些方法就是给组件中注册事件监听器的方法,只是【不同类型的事件】需要使用【不同类型的监听器】来监听,所以不同的addXxxxListener方法就表示给组件添加相应的事件监听器。(Xxxx代表事件的类型)

    2)事件对象及其对应的处理接口(也就是事件监听器)
    注:事件处理器都被定义为了接口,思考为什么都定义为接口

    java.util.EventObject类
    public class EventObject extends Object{}

    该类是java中所有事件对象的父类型。
    该类中有一个非常重要的方法:getSource
    public Object getSource(){...}
    该方法返还的对象是产生当前事件的事件源
    例如:当前使用鼠标点击按钮btn的时候,会产生一个事件对象e,这个对象e就表示鼠标点击的事件,同时e也是EventObject类型的对象,调用getSource方法可以得到产生事件的事件源,也就是我们点击的那个按钮btn.

    java.awt.Event类
    public class Event extends Object{..}
    在Java1.1和以后的版本中该类已被废弃,由AWTEvent类及其子类所取代.



    java.awt.AWTEvent类
    public abstract class AWTEvent extends EventObject{...}
    该类是所有AWT事件的父类型,此类及其子类取代了原来的 java.awt.Event类

    java.awt.event.ActionEvent类
    public class ActionEvent extends AWTEvent{...}
    动作事件类,单击按钮、选择菜单项或在文本框中按回车时可产生此事件对象。
    注:定时器Timer 也可以产生ActionEvent类型的事件

    可以处理该类型事件的监听器接口:ActionListener
    注:ActionListener是一个很通用的接口,可以处理很多种组件上面产生的事件.
    例如: ActionEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    JButton btn = new JButton("测试");
    btn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    System.out.println("hello");
    }
    });

    panel.add(btn);

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);

    java.awt.event.AdjustmentEvent类
    public class AdjustmentEvent extends AWTEvent{..}
    调整事件类,当改变滚动条滑块位置时可产生此事件对象。

    该类代表由Adjustable类型对象所发出的调整事件。主要针对的是滚动条,Scrollbar和JScrollbar都是Adjustable接口的实现类。

    可以处理该类型事件的监听器接口:AdjustmentListener
    例如: AdjustmentEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    JScrollBar bar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 0, 0, 100);
    bar.setPreferredSize(new Dimension(100, 20));
    bar.addAdjustmentListener(new AdjustmentListener() {
    @Override
    public void adjustmentValueChanged(AdjustmentEvent e) {
    System.out.println(e.getValue());
    }
    });

    panel.add(bar);

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);



    java.awt.event.ComponentEvent类
    public class ComponentEvent extends AWTEvent{...}
    组件事件类,表示组件被移动、大小被更改或可见性被更改的事件,同时它也是其他组件事件的父类:
    java.awt.event.ContainerEvent
    java.awt.event.FocusEvent
    java.awt.event.WindowEvent
    ..
    这些都是它的的子类

    可以处理该类型事件的监听器接口:ComponentListener
    该接口中有四个抽象方法:
    componentMoved组件移动时被调用
    componentResized组件缩放时被调用
    componentShown组件显示时被调用
    componentHidden组件隐藏时被调用
    例如:调用jFrame.setVisible(false);

    例如:ComponentEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    jFrame.addComponentListener(new ComponentListener() {
    public void componentShown(ComponentEvent e) {
    System.out.println("shown");
    }
    public void componentHidden(ComponentEvent e) {
    System.out.println("Hidden");
    }
    public void componentResized(ComponentEvent e) {
    System.out.println("Resized");
    }
    public void componentMoved(ComponentEvent e) {
    System.out.println("Moved");
    }
    });

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);



    java.awt.event.ContainerEvent类
    public class ContainerEvent extends ComponentEvent{..}
    容器事件类,容器中因为添加或移除组件而更改的事件。

    可以处理该类型事件的监听器接口:ContainerListener
    接口中有俩个方法:
    componentAdded添加组件时被调用
    componentRemoved移除组件时被调用

    例如:ContainerEventTest.java

    JFrame jFrame = new JFrame();
    final JPanel panel = new JPanel();

    JButton btn = new JButton("点击");
    final JButton test = new JButton("测试");

    btn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    panel.add(test);
    //在运行中动态添加组件
    //需要调用容器的validate和repaint
    //或者是调用容器的revalidate方法
    //否则动态添加的组件不显示
    //panel.validate();
    //panel.repaint();
    panel.revalidate();
    }
    });

    panel.addContainerListener(new ContainerListener() {

    @Override
    public void componentRemoved(ContainerEvent e) {
    System.out.println("removed");
    }

    @Override
    public void componentAdded(ContainerEvent e) {
    System.out.println("Added");
    }
    });

    panel.add(btn);

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);



    java.awt.event.WindowEvent类
    public class WindowEvent extends ComponentEvent{..}
    窗口事件类,窗口打开、关闭等操作是会创建该事件对象。

    可以处理该类型事件的监听器接口:WindowListener
    该接口中有七个方法:
    windowOpened窗口打开后被调用
    windowClosed窗口关闭后被调用
    windowClosing窗口关闭时被调用
    windowActivated窗口激活时被调用
    windowDeactivated窗口失去焦点时被调用
    windowIconified窗口最小化时被调用
    windowDeiconified最小化窗口还原时被调用

    例如:WindowEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    jFrame.addWindowListener(new WindowListener() {
    public void windowOpened(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {
    System.out.println("最小化窗口");
    }
    public void windowDeiconified(WindowEvent e) {
    System.out.println("最小化窗口被还原");
    }
    public void windowDeactivated(WindowEvent e) {}
    public void windowClosing(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    });

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);


    java.awt.event.FocusEvent类
    public class FocusEvent extends ComponentEvent{...}
    焦点事件类,当组件获得或者失去焦点的时候回产生该类型的事件对象。

    可以处理该类型事件的监听器接口:FocusListener
    该接口中有俩个方法:
    focusGained组件获得焦点时被调用
    focusLost组件失去焦点时被调用

    例如:FocusEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    JTextField field = new JTextField(10);
    JButton btn = new JButton("test");

    field.addFocusListener(new FocusListener() {
    public void focusLost(FocusEvent e) {
    System.out.println("失去焦点");
    }
    public void focusGained(FocusEvent e) {
    System.out.println("获得焦点");
    }
    });

    panel.add(field);
    panel.add(btn);

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);

    java.awt.event.ItemEvent类
    public class ItemEvent extends AWTEvent{..}
    选择事件类,选择复选框、选项框、单击列表框等时会产该事件对象。

    可以处理该类型事件的监听器接口:ItemListener

    例如:ItemEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    JCheckBox jck = new JCheckBox("自动登录");
    jck.addItemListener(new ItemListener() {
    @Override
    public void itemStateChanged(ItemEvent e) {
    System.out.println(e.getStateChange());
    }
    });
    panel.add(jck);

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);


    注:
    item的状态发生改变时触发该事件,item在这里的状态有两个,Selected 和 deSelected(即选中和未被选中),所以,当改变"下拉列表"中被选中的项的时候,其实是触发了两次事件,第一次是上次被选中的项的 State 由 Selected 变为 deSelected ,即取消选择, 第二次是本次被选中的项的 State 由 deSelected 变为 Selected ,即新选中,所以,这时候的 ItemStateChanged 事件中的代码要被执行两次了。
    这种情况做一个判断即可
    if(e.getStateChange() == ItemEvent.SELECTED){
       //要执行的代码
      }



    java.awt.event.TextEvent类
    public class TextEvent extends AWTEvent{..}
    文本内容类,组件中的文本已改变时会产生该事件对象。

    可以处理该类型事件的监听器接口:TextListener

    例如:TextEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    TextField field = new TextField(10);
    field.setText("hello");
    field.addTextListener(new TextListener() {
    @Override
    public void textValueChanged(TextEvent e) {
    System.out.println("改变了");
    }
    });

    panel.add(field);

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);

    注:如果是JTextField,那么需要这样监听内容的改变:
    JTextField field = new JTextField(10);
    field.getDocument().addDocumentListener(new DocumentListener() {
    public void removeUpdate(DocumentEvent e) {

    }
    public void insertUpdate(DocumentEvent e) {

    }
    public void changedUpdate(DocumentEvent e) {

    }
    });



    java.awt.event.KeyEvent类
    public class KeyEvent extends InputEvent{..}
    键盘事件类,键盘输入的时候会产生此事件对象。
    注:InputEvent是ComponentEvent的子类,ComponentEvent类在上面已经介绍过了。
    public abstract class InputEvent extends ComponentEvent {}


    可以处理该类型事件的监听器接口:KeyListener
    该接口中有三个方法:
    keyPressed键按下时被调用
    keyReleased键释放时被调用
    keyTyped键入某个键时被调用(F1等功能按键时不会触发)

    注:KeyEvent类中定义了很多静态常量,几乎把键盘上所以的按键都表示出来了。
    例如:KeyEvent.VK_ENTER表示回车键,VK指的是Virtual-Key(虚拟键码VK值)

    例如:KeyEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    JTextField field = new JTextField(10);

    field.addKeyListener(new KeyListener() {

    @Override
    public void keyTyped(KeyEvent e) {
    System.out.println("keyTyped "+e.getKeyCode()+" "+e.getKeyChar());
    }

    @Override
    public void keyReleased(KeyEvent e) {
    System.out.println("keyReleased "+e.getKeyCode());
    }

    @Override
    public void keyPressed(KeyEvent e) {
    System.out.println("keyPressed "+e.getKeyCode());
    }
    });

    panel.add(field);

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);

    java.awt.event.MouseEvent类
    public class MouseEvent extends InputEvent{..}
    鼠标事件类,当鼠标在组件中发生鼠标动作的时候会产生此事件对象。

    有三个接口可以处理该类型事件:
    MouseListener接口
    MouseMotionListener接口
    MouseWheelListener接口

    MouseListener接口中有五个方法:
    mouseClicked 鼠标单击时被调用
    mouseEntered 鼠标进入时被调用
    mouseExited 鼠标离开时被调用
    mousePressed 鼠标键按下时被调用
    mouseReleased鼠标键释放时被调用

    MouseMotionListener接口中有俩个方法:
    mouseMoved 鼠标移动时被调用
    mouseDragged鼠标拖拽时被调用

    MouseWheelListener接口中有一个方法:
    mouseWheelMoved 鼠标滚轮滚动时被调用


    例如:MouseEventTest.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    panel.addMouseListener(new MouseListener() {
    public void mouseReleased(MouseEvent e) {
    System.out.println("mouseReleased");
    }
    public void mousePressed(MouseEvent e) {
    System.out.println("mousePressed");
    }
    public void mouseExited(MouseEvent e) {
    System.out.println("mouseExited");
    }
    public void mouseEntered(MouseEvent e) {
    System.out.println("mouseEntered");
    }
    public void mouseClicked(MouseEvent e) {
    System.out.println("mouseClicked");
    }
    });

    panel.addMouseMotionListener(new MouseMotionListener() {
    public void mouseMoved(MouseEvent e) {
    System.out.println("mouseMoved");
    }
    public void mouseDragged(MouseEvent e) {
    System.out.println("mouseDragged");
    }
    });

    panel.addMouseWheelListener(new MouseWheelListener() {
    public void mouseWheelMoved(MouseWheelEvent e) {
    System.out.println("mouseWheelMoved");
    }
    });


    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.add(panel);
    jFrame.setVisible(true);

    3.适配器 Adapter
    很多监听器接口中都定义了很多个方法,每个方法负责处理一种产生事件的情况,我们编写实现类的时候就需要实现监听器接口中的所有方法,但是很多时候我们其实只需要调用接口中的一个方法,但是由于语法要求我们还是必须把接口中的所有抽象全都实现了。
    例如: 点击按钮输出hello world
    JButton btn = new JButton("test");
    btn.addMouseListener(new MouseListener() {
    public void mouseClicked(MouseEvent e) {
    System.out.println("hello world");
    }
    public void mouseReleased(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    });

    使用了MouseListener接口的匿名内部类对象,并且五个方法全都实现了,但是其实我们只需要调用mouseClicked方法.


    为了处理这个代码中出现的情况,又引入了接口的适配器类:XxxxAdapter

    MouseAdapter实现了MouseListener, MouseWheelListener, MouseMotionListener三个接口,并且把接口中抽象方法全都进行了空实现,将来我们只需要创建MouseAdapter类的匿名内部类然后重写我们想调用的方法即可
    例如: 点击按钮输出hello world
    JButton btn = new JButton("test");
    btn.addMouseListener(new MouseAdapter() {
    public void mouseClicked(MouseEvent e) {
    System.out.println("hello world");
    }
    });


    除了MouseAdapter实现MouseListener, MouseWheelListener, MouseMotionListener三个接口,是一个适配器类之外,还有其他的一些适配器类:

    WindowAdapter适配器类实现了WindowListener, WindowStateListener, WindowFocusListener三个接口

    ComponentAdapter适配器类实现了ComponentListener接口

    ContainerAdapter适配器类实现了ContainerListener接口

    FocusAdapter适配器类实现了FocusListener接口

    KeyAdapter适配器类实现了KeyListener接口

    MouseMotionAdapter适配器类实现了MouseMotionListener接口

    HierarchyBoundsAdapter适配器类实现了HierarchyBoundsListener接口


    4.定时器Timer
    javax.swing.Timer类,可以定时触发事件(ActionEvent),调用监听器的指定方法。

    例如:TimerTest1.java TimerTest2.java

    JFrame jFrame = new JFrame();
    JPanel panel = new JPanel();

    JPanel north = new JPanel();
    JButton startBtn = new JButton("开始");
    JButton endBtn = new JButton("停止");

    final Canvas canvas = new Canvas();

    final Timer timer = new Timer(500,new ActionListener() {
    private int count;
    @Override
    public void actionPerformed(ActionEvent e) {
    if(count*10>=canvas.getWidth()){
    return ;
    }
    Graphics g = canvas.getGraphics();
    g.drawLine(count*10, 0, count*10, canvas.getWidth());
    count++;
    }
    });

    startBtn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
    timer.start();
    }
    });
    endBtn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
    timer.stop();
    }
    });

    north.add(startBtn);
    north.add(endBtn);

    panel.setLayout(new BorderLayout());
    panel.add(canvas);

    jFrame.add(north,BorderLayout.NORTH);
    jFrame.add(panel);

    jFrame.setSize(400, 400);
    jFrame.setLocation(700, 300);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.setVisible(true);



    5.让当前类实现监听器接口
    当前对象this就成为了监听器对象
    例如:
    public class Test extends JFrame implements ActionListener{
    private static final long serialVersionUID = 1L;

    private JPanel jPanel;
    private JButton btn;

    public Test() {
    setBounds(700, 500, 500, 500);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setResizable(false);
    initComponet();
    setVisible(true);
    }

    private void initComponet(){
    //初始化组件
    jPanel = new JPanel();
    btn = new JButton("测试");

    //设置布局管理器并添加组件
    jPanel.add(btn);

    add(jPanel);

    //给组件添加事件监听器
    btn.addActionListener(this);
    }
    public void actionPerformed(ActionEvent e) {
    System.out.println("hello world");
    }

    public static void main(String[] args) {
    new Test();
    }
    }

  • 相关阅读:
    js 中 && 和 ||
    The server time zone value 'EDT' is unrecognized or represents more than one time zone.
    docker进入容器
    docker 挂载本地目录
    Docker for Windows 挂载目录失败
    docker下redis启动 根据本地配置文件
    docker 安装 nacos/nacos-server 镜像并配置本地数据库
    spring cloud Nacos Config配置中心
    Docker卸载
    虚拟机centos添加硬盘和分区挂载
  • 原文地址:https://www.cnblogs.com/yue-170305/p/11478931.html
Copyright © 2020-2023  润新知