Java语言程序设计——篇十五(1)

在这里插入图片描述
在这里插入图片描述

       🌿🌿🌿跟随博主脚步,从这里开始→博主主页🌿🌿🌿

  • 欢迎大家:这里是我的学习笔记、总结知识的地方,喜欢的话请三连,有问题可以私信🌳🌳🌳
    您的点赞👍、关注➕、收藏⭐️、评论📝、私信📧是我最大的支持与鼓舞!!!🌻🌻🌻

在这里插入图片描述

事件处理

  • 事件处理:为控件设计相应的程序,使控件能够响应并处理用户的操作。
  • Java程序一旦构建完GUI,就不再工作,而是等待用户通过鼠标、键盘给它通知,它再根据这个通知的内容进行相应的处理 (事件处理)
  • 通常一个键盘或鼠标操作会引发一个系统预先定义好的事件 (事件类) ,用户只需编写代码,定义每个特定事件发生时程序应做出何种响应即可。

事件处理模型

  • JavaFX事件处理采用事件代理模型(委托事件模型):将事件源和对事件做出的具体处理分离开来。将事件的处理从事件源对象代理给一个或多个成为事件处理器或事件监听器的对象,事件由事件处理器处理。
  • 事件处理模型涉及3种对象:事件源、事件和事件处理器(监听者):
    (1)事件源(event source):能够产生事件的对象。如按钮、鼠标、文本框、键盘等。当这些对象的状态改变时,就会产生事件。
    (2)事件(event):一个事件是事件类的实例,描述事件源状态的改变。
    (3)事件处理器(handler):接收事件并对其进行处理的对象。该对象必须实现EventHandler接口。处理器有专门的方法来处理事件,事件处理器是一个对事件源进行监视的对象,当事件源上发生事件时,事件处理器能够监听到,并调用相应的方法对发生的事件做出相应的处理。
  • JavaFX的事件处理模型如图所示:
    在这里插入图片描述
  • 例如,当按钮被鼠标单击时,会触发一个“动作事件”(Action event),JavaFX程序就会产生一个“事件对象”来表示这个事件,然后把这个“事件对象”传递给“事件处理器”,“事件处理器”再依据“事件对象”的种类把工作指派给事件处理者,即事件处理程序。在这里按钮就是一个事件源。
  • 为了让“事件源”(如按钮)知道要把事件信息传递给哪一个“事件处理器”,事先必须把“事件处理器”向“事件源”注册(register),这个操作也就是告知“事件源”要把事件信息传递给它。
  • 事件代理模型的工作原理: 在这里插入图片描述
    总结:
      要处理事件,首先在事件源上注册事件处理器。当用户动作触发一个事件,运行时系统将创建一个事件对象,然后执行事件处理器对象。

事件类和事件类型

  • JavaFX定义了大量事件类用于处理各种用户操作所产生的事件,这些类封装了事件对象。在Java语言中,Java事件类的根是java.util.EventObjectJavaFX事件类的根是javafx.event.Event
  • 常用事件类的层次关系如下图:
    在这里插入图片描述
  • 事件类型是javafx.event.EventType类的实例,它表示与事件相关的具体类型。事件类型还可进一步分为单个的事件类。
  • 如KeyEvent类就包含下面的事件类型:

KeyEvent.KEY_PRESSED:键被按下。
KeyEvent.KEY_RELEASED:键被释放。
KeyEvent.KEY_TYPED:键被按下,然后释放

  • MouseEvent类包含10多个具体事件,下面是几个常用的:

MouseEvent.MOUSE_CLICKED,鼠标单击。
MouseEvent.MOUSE_ENTERED ,鼠标进入控件。
MouseEvent.MOUSE_PRESSED,按下鼠标左键。
MouseEvent.MOUSE_MOVED,鼠标指针移动。

使用事件处理器

  • 担当事件源的事件处理器,需满足两个条件:
    (1)事件处理器必须是一个对应的事件处理器接口的实例。
    (2)事件处理器对象必须通过事件源进行注册,注册方法依赖于事件类型。
  • 注册事件处理器的两种方法:
    (1)使用控件提供的方便方法。教材中表15-2给出常用事件类型、用户动作和事件注册方法。
    (2)使用Node类的addEventHandler()的方法,该方法带一个事件类型参数和一个EventHandler参数。
    1.使用控件提供的方便方法来注册事件处理器,不同的事件注册方法不同。例如:
    ①对于ActionEvent事件,注册方法是
   setOnAction(EventHandler<ActionEvent> handler)

②对于鼠标单击事件,注册方法是

setOnMouseClicked(EventHandler<MouseEvent> handler)

③对于一个按键事件,注册方法是

setOnKeyPressed(EventHandler<KeyEvent> handler);

2.使用Node类的addEventHandler()的方法:
  JavaFX定义了一个对于事件T的统一的处理器接口EventHandler<T extends Event>,该接口中声明了handle(T e)方法用于处理事件。例如:
   对于ActionEvent事件,处理器接口是EventHandler(ActionEvent),应该实现handle(ActionEvente)方法处理事件。
实现事件处理器对象和注册事件处理器的三种方法:
(1)通过内部类对象实现;
(2)通过匿名内部类实现;
(3)使用Lambda表达式实现。

实战演练

例:下面代码使用匿名类创建一个处理器对象,处理鼠标事件,并为节点注册事件处理器。

//定义事件处理器handler 
EventHandler handler = new EventHandler<MouseEvent>() {
      public void handle(MouseEvent event) {
               System.out.println("处理事件:" + event.getEventType());}};
//为节点注册处理器handler1) myNode.setOnMouseClicked(handler);2)myNode.addEventHandler(MouseEvent.MOUSE_CLICKED,
                          handler);

常用事件类型

(1)动作事件ActionEvent

  • ActionEvent是表示某种动作的事件,如按钮被点击、菜单项被选择,都发生这种类型事件。
  • 使用控件的setOnAction()方法,一般格式为:
void setOnAction(EventHandler<ActionEvent> value)//事件处理器对象
  • 使用Node类定义的addEventHandler()方法注册事件处理器:
    void addEventHandler(ActionEvent eventType,
                  EventHandler<ActionEvent> handler)
实战演练

问题描述:
编写程序,实现如图所示的界面。要求当单击“确定或“取消”按钮时,在标签中显示相应信息。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
例:使用Lambda表达式实现处理器

 public class ActionEventDemo extends Application {
       Label label = new Label();
       Button ok = new Button("确定"), cancel = new Button("取消");
       @Override
       public void start(Stage stage) {
       ok.setOnAction((ActionEvent event)->label.setText("你单击了'确定'按钮"));
   cancel.setOnAction((ActionEvent event)->label.setText("你单击了'取消'按钮"));
	FlowPane rootNode = new FlowPane(10, 10);
	rootNode.setAlignment(Pos.CENTER);
	rootNode.getChildren().addAll(ok, cancel, label);
	Scene scene = new Scene(rootNode, 240, 100);
	stage.setTitle("事件处理示例");
	stage.setScene(scene);
	stage.show();
     }
        public static void main(String[] args) {
		launch(args);
    }
}

2)鼠标事件MouseEvent

  • 当鼠标按键在一个节点上或者一个场景中被按下、释放、单击、移动或者拖动时,一个MouseEvent事件被触发。
  • MouseEvent类的常用方法:

MouseButton getButton()//结果是MouseButton枚举值。PRIMARY、MIDDLE、SECONDARY。
例:me.getButton()==MouseButton.SECONDARY
int getClickCount()
double getX()
double getY()
double getScreenX()
double getScreenY()

可以使用setOnMouseEntered()、setOnMouseExited()和setOnMousePressed()等方法为鼠标事件注册事件处理器。

实战演练

问题描述:
编写程序,如图所示。当鼠标进入圆、离开圆、在圆中按键,在标签中显示相关信息,当鼠标指针处于圆中并拖动,圆在新的位置显示。

import javax.swing.*;  
import java.awt.*;  
import java.awt.event.*;  
  
public class CircleApp extends JFrame {  
    private JLabel statusLabel;  
    private int circleX = 100;  
    private int circleY = 100;  
    private int circleRadius = 50;  
  
    public CircleApp() {  
        setTitle("Circle App");  
        setSize(400, 400);  
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        setLayout(null);  
  
        statusLabel = new JLabel("Mouse outside the circle");  
        statusLabel.setBounds(10, 10, 380, 20);  
        add(statusLabel);  
  
        addMouseListener(new MouseAdapter() {  
            @Override  
            public void mousePressed(MouseEvent e) {  
                if (isInsideCircle(e.getX(), e.getY())) {  
                    statusLabel.setText("Mouse pressed inside the circle");  
                }  
            }  
  
            @Override  
            public void mouseReleased(MouseEvent e) {  
                if (isInsideCircle(e.getX(), e.getY())) {  
                    statusLabel.setText("Mouse released inside the circle");  
                }  
            }  
  
            @Override  
            public void mouseEntered(MouseEvent e) {  
                if (isInsideCircle(e.getX(), e.getY())) {  
                    statusLabel.setText("Mouse entered the circle");  
                }  
            }  
  
            @Override  
            public void mouseExited(MouseEvent e) {  
                statusLabel.setText("Mouse outside the circle");  
            }  
        });  
  
        addMouseMotionListener(new MouseMotionAdapter() {  
            @Override  
            public void mouseDragged(MouseEvent e) {  
                if (isInsideCircle(e.getX(), e.getY())) {  
                    circleX = e.getX() - circleRadius;  
                    circleY = e.getY() - circleRadius;  
                    repaint();  
                }  
            }  
        });  
    }  
  
    private boolean isInsideCircle(int x, int y) {  
        return Math.sqrt(Math.pow(x - circleX - circleRadius, 2) + Math.pow(y - circleY - circleRadius, 2)) <= circleRadius;  
    }  
  
    @Override  
    public void paint(Graphics g) {  
        super.paint(g);  
        g.drawOval(circleX, circleY, 2 * circleRadius, 2 * circleRadius);  
    }  
  
    public static void main(String[] args) {  
        SwingUtilities.invokeLater(() -> {  
            CircleApp frame = new CircleApp();  
            frame.setVisible(true);  
        });  
    }  
}

(3)键盘事件KeyEvent

  • 在一个节点或者一个场景上按下、释放或者敲击键盘按钮,就会触发一个KeyEvent事件。
  • KeyEvent类的常用方法:

String getCharacter()
String getText()
KeyCode getCode()
boolean isShiftDown()

使用节点的setOnKeyPressed()、setOnKeyReleased()和setOnKeyTyped()等方法为键盘事件注册事件处理器。

实战演练

问题描述:
编写程序,如图所示。按字母键显示不同字母,按方向键,字母移动。

import javafx.application.Application;  
import javafx.scene.Scene;  
import javafx.scene.input.KeyCode;  
import javafx.scene.layout.StackPane;  
import javafx.scene.paint.Color;  
import javafx.scene.shape.Rectangle;  
import javafx.scene.text.Font;  
import javafx.scene.text.Text;  
import javafx.stage.Stage;  
  
public class KeyboardEventsExample extends Application {  
  
    private Text text = new Text(50, 50, "A");  
    private double x = 50, y = 50;  
  
    @Override  
    public void start(Stage primaryStage) {  
        Rectangle background = new Rectangle(400, 400, Color.WHITE);  
        StackPane root = new StackPane();  
        root.getChildren().addAll(background, text);  
  
        Scene scene = new Scene(root, 400, 400);  
  
        scene.setOnKeyPressed(event -> {  
            KeyCode keyCode = event.getCode();  
            switch (keyCode) {  
                case UP:  
                    y -= 10;  
                    text.setY(y);  
                    break;  
                case DOWN:  
                    y += 10;  
                    text.setY(y);  
                    break;  
                case LEFT:  
                    x -= 10;  
                    text.setX(x);  
                    break;  
                case RIGHT:  
                    x += 10;  
                    text.setX(x);  
                    break;  
                default:  
                    text.setText(keyCode.toString().substring(0, 1));  
                    break;  
            }  
        });  
  
        primaryStage.setTitle("JavaFX Keyboard Event Example");  
        primaryStage.setScene(scene);  
        primaryStage.show();  
    }  
  
    public static void main(String[] args) {  
        launch(args);  
    }  
}

博主用心写,读者点关注,互动传真情,知识不迷路。

本书是Java语言的经典教材,多年来畅销不衰。本书全面整合了Java 8的特性,采用“基础优先,问题驱动”的教学方式,循序渐进地介绍了程序设计基础、解决问题的方法、面向对象程序设计、图形用户界面设计、异常处理、I/O和递归等内容。此外,本书还全面且深入地覆盖了一些高级主题,包括算法和数据结构、多线程、网络、国际化、高级GUI等内容。 本书中文版由《Java语言程序设计 基础》和《Java语言程序设计 进阶》组成。基础对应原书的第1~18章,进阶对应原书的第19~33章。为满足对Web设计有浓厚兴趣的同学,本版在配套网站上增加了第34~42章的内容,以提供更多的相关信息。 本书特点 基础介绍基础内容,进阶介绍高级内容,便于教师按需选择理想的教材。 全面整合了Java 8的特性,对全书的内容进行了修订和更新,以反映Java程序设计的全新技术发展。 对面向对象程序设计进行了深入论述,包含GUI程序设计的基础和扩展。 提供的大量示例中都包括了对问题求解的详细步骤,很多示例都是随着Java技术的引入不断地进行增强,这种循序渐进的讲解方式更易于学生学习。 用JavaFX取代了Swing,极大地简化了GUI编程,比Swing更易于学习。 更多有趣示例和练习,激发学生兴趣。在配套网站上还为教师提供了100多道的编程练习题。 作者简介
评论 88
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倾听一世,繁花盛开

你的鼓励是我创作最大的动力与支

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值