JavaFX - Xử lý sự kiện

Trong JavaFX, chúng ta có thể phát triển các ứng dụng GUI, ứng dụng web và ứng dụng đồ họa. Trong các ứng dụng như vậy, bất cứ khi nào người dùng tương tác với ứng dụng (các nút), một sự kiện được cho là đã xảy ra.

Ví dụ, nhấp vào một nút, di chuyển chuột, nhập ký tự thông qua bàn phím, chọn một mục từ danh sách, cuộn trang là những hoạt động gây ra một sự kiện xảy ra.

Các loại sự kiện

Các sự kiện có thể được phân loại rộng rãi thành hai loại sau:

  • Foreground Events- Những sự kiện yêu cầu sự tương tác trực tiếp của người dùng. Chúng được tạo ra do hậu quả của việc một người tương tác với các thành phần đồ họa trong Giao diện người dùng đồ họa. Ví dụ: nhấp vào nút, di chuyển chuột, nhập ký tự qua bàn phím, chọn một mục từ danh sách, cuộn trang, v.v.

  • Background Events- Những sự kiện yêu cầu sự tương tác của người dùng cuối được gọi là sự kiện nền. Hệ điều hành bị gián đoạn, lỗi phần cứng hoặc phần mềm, hết hạn hẹn giờ, hoàn thành hoạt động là ví dụ về các sự kiện nền.

Sự kiện trong JavaFX

JavaFX cung cấp hỗ trợ để xử lý nhiều loại sự kiện. Lớp có tênEvent của gói javafx.event là lớp cơ sở cho một sự kiện.

Một thể hiện của bất kỳ lớp con nào của nó là một sự kiện. JavaFX cung cấp nhiều loại sự kiện. Một số trong số họ được liệt kê dưới đây.

  • Mouse Event- Đây là sự kiện đầu vào xảy ra khi nhấp chuột. Nó được đại diện bởi lớp có tênMouseEvent. Nó bao gồm các hành động như nhấp chuột, nhấn chuột, thả chuột, di chuyển chuột, chuột đã nhập mục tiêu, chuột đã thoát mục tiêu, v.v.

  • Key Event- Đây là sự kiện đầu vào cho biết hành trình phím xảy ra trên một nút. Nó được đại diện bởi lớp có tênKeyEvent. Sự kiện này bao gồm các hành động như nhấn phím, nhả phím và nhập phím.

  • Drag Event- Đây là sự kiện đầu vào xảy ra khi chuột được kéo. Nó được đại diện bởi lớp có tênDragEvent. Nó bao gồm các hành động như kéo đã nhập, kéo thả, kéo mục tiêu đã nhập, kéo mục tiêu đã thoát, kéo qua, v.v.

  • Window Event- Đây là sự kiện liên quan đến hành động hiển thị / ẩn cửa sổ. Nó được đại diện bởi lớp có tênWindowEvent. Nó bao gồm các hành động như ẩn cửa sổ, hiển thị cửa sổ, ẩn cửa sổ, hiển thị cửa sổ, v.v.

Xử lý sự kiện

Xử lý sự kiện là cơ chế kiểm soát sự kiện và quyết định điều gì sẽ xảy ra, nếu sự kiện xảy ra. Cơ chế này có mã được gọi là trình xử lý sự kiện được thực thi khi một sự kiện xảy ra.

JavaFX cung cấp trình xử lý và bộ lọc để xử lý các sự kiện. Trong JavaFX mọi sự kiện đều có:

  • Target- Nút mà một sự kiện đã xảy ra. Mục tiêu có thể là một cửa sổ, khung cảnh và một nút.

  • Source- Nguồn mà sự kiện được tạo ra sẽ là nguồn của sự kiện. Trong trường hợp trên, chuột là nguồn của sự kiện.

  • Type- Loại sự kiện đã xảy ra; trong trường hợp sự kiện chuột - chuột được nhấn, chuột thả ra là các loại sự kiện.

Giả sử rằng chúng ta có một ứng dụng có các nút Vòng tròn, Ngừng và Phát được chèn bằng cách sử dụng một đối tượng nhóm như sau:

Nếu bạn nhấp vào nút phát, nguồn sẽ là chuột, nút đích sẽ là nút phát và loại sự kiện được tạo ra là nhấp chuột.

Các giai đoạn xử lý sự kiện trong JavaFX

Bất cứ khi nào một sự kiện được tạo, JavaFX sẽ trải qua các giai đoạn sau.

Xây dựng tuyến đường

Bất cứ khi nào một sự kiện được tạo, lộ trình mặc định / ban đầu của sự kiện được xác định bằng cách xây dựng Event Dispatch chain. Nó là đường dẫn từ sân khấu đến Node nguồn.

Sau đây là chuỗi điều phối sự kiện cho sự kiện được tạo, khi chúng ta nhấp vào nút phát trong trường hợp trên.

Giai đoạn ghi lại sự kiện

Sau khi xây dựng chuỗi điều phối sự kiện, nút gốc của ứng dụng gửi sự kiện. Sự kiện này truyền đến tất cả các nút trong chuỗi điều phối (từ trên xuống dưới). Nếu bất kỳ nút nào trong số này cófilterđã đăng ký cho sự kiện đã tạo, nó sẽ được thực thi. Nếu không có nút nào trong chuỗi điều phối có bộ lọc cho sự kiện được tạo, thì nó được chuyển đến nút đích và cuối cùng nút đích xử lý sự kiện.

Giai đoạn tạo bong bóng sự kiện

Trong giai đoạn sủi bọt sự kiện, sự kiện được di chuyển từ nút đích đến nút giai đoạn (từ dưới lên trên). Nếu bất kỳ nút nào trong chuỗi điều phối sự kiện cóhandlerđã đăng ký cho sự kiện đã tạo, nó sẽ được thực thi. Nếu không có nút nào trong số các nút này có trình xử lý để xử lý sự kiện, thì sự kiện sẽ đến nút gốc và cuối cùng quá trình sẽ được hoàn thành.

Bộ xử lý và bộ lọc sự kiện

Bộ lọc sự kiện và trình xử lý là những bộ lọc chứa logic ứng dụng để xử lý một sự kiện. Một nút có thể đăng ký nhiều hơn một bộ xử lý / bộ lọc. Trong trường hợp các nút cha-con, bạn có thể cung cấp một bộ lọc / xử lý chung cho các nút cha, được xử lý như mặc định cho tất cả các nút con.

Như đã đề cập ở trên, trong sự kiện, xử lý là một bộ lọc được thực thi và trong giai đoạn tạo bọt sự kiện, một trình xử lý được thực thi. Tất cả các trình xử lý và bộ lọc triển khai giao diệnEventHandler của gói javafx.event.

Thêm và xóa bộ lọc sự kiện

Để thêm bộ lọc sự kiện vào một nút, bạn cần đăng ký bộ lọc này bằng phương pháp addEventFilter() sau đó Node lớp học.

//Creating the mouse event handler 
EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() { 
   @Override 
   public void handle(MouseEvent e) { 
      System.out.println("Hello World"); 
      circle.setFill(Color.DARKSLATEBLUE);  
   } 
};   
//Adding event Filter 
Circle.addEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);

Theo cách tương tự, bạn có thể xóa bộ lọc bằng phương thức removeEventFilter () như hình dưới đây:

circle.removeEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);

Ví dụ về xử lý sự kiện

Sau đây là một ví dụ minh họa việc xử lý sự kiện trong JavaFX bằng cách sử dụng các bộ lọc sự kiện. Lưu mã này trong một tệp có tênEventFiltersExample.java.

import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.event.EventHandler;
 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Circle; 

import javafx.scene.text.Font; 
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text; 
import javafx.stage.Stage; 
         
public class EventFiltersExample extends Application { 
   @Override 
   public void start(Stage stage) {      
      //Drawing a Circle 
      Circle circle = new Circle(); 
      
      //Setting the position of the circle 
      circle.setCenterX(300.0f); 
      circle.setCenterY(135.0f); 
      
      //Setting the radius of the circle 
      circle.setRadius(25.0f); 
      
      //Setting the color of the circle 
      circle.setFill(Color.BROWN); 
      
      //Setting the stroke width of the circle 
      circle.setStrokeWidth(20);      
       
      //Setting the text 
      Text text = new Text("Click on the circle to change its color"); 
      
      //Setting the font of the text 
      text.setFont(Font.font(null, FontWeight.BOLD, 15));     
      
      //Setting the color of the text 
      text.setFill(Color.CRIMSON); 
  
      //setting the position of the text 
      text.setX(150); 
      text.setY(50); 
       
      //Creating the mouse event handler 
      EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() { 
         @Override 
         public void handle(MouseEvent e) { 
            System.out.println("Hello World"); 
            circle.setFill(Color.DARKSLATEBLUE);
         } 
      };  
      //Registering the event filter 
      circle.addEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);   
       
      //Creating a Group object  
      Group root = new Group(circle, text); 
         
      //Creating a scene object 
      Scene scene = new Scene(root, 600, 300); 
       
      //Setting the fill color to the scene 
      scene.setFill(Color.LAVENDER);  
      
      //Setting title to the Stage 
      stage.setTitle("Event Filters Example");       
         
      //Adding scene to the stage 
      stage.setScene(scene); 
         
      //Displaying the contents of the stage 
      stage.show(); 
   } 
   public static void main(String args[]){ 
      launch(args); 
   } 
}

Biên dịch và thực thi tệp java đã lưu từ dấu nhắc lệnh bằng các lệnh sau.

javac EventFiltersExample.java 
java EventFiltersExample

Khi thực thi, chương trình trên tạo một cửa sổ JavaFX như hình dưới đây.

Thêm và xóa trình xử lý sự kiện

Để thêm một trình xử lý sự kiện vào một nút, bạn cần đăng ký trình xử lý này bằng phương thức addEventHandler() sau đó Node lớp như hình bên dưới.

//Creating the mouse event handler 
EventHandler<javafx.scene.input.MouseEvent> eventHandler = 
   new EventHandler<javafx.scene.input.MouseEvent>() { 
   
   @Override 
   public void handle(javafx.scene.input.MouseEvent e) { 
      System.out.println("Hello World"); 
      circle.setFill(Color.DARKSLATEBLUE);             
   } 
};    
//Adding the event handler 
circle.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, eventHandler);

Theo cách tương tự, bạn có thể loại bỏ trình xử lý sự kiện bằng phương thức removeEventHandler () như hình dưới đây:

circle.removeEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler);

Thí dụ

Chương trình sau đây là một ví dụ minh họa việc xử lý sự kiện trong JavaFX bằng cách sử dụng các trình xử lý sự kiện.

Lưu mã này trong một tệp có tên EventHandlersExample.java.

import javafx.animation.RotateTransition; 
import javafx.application.Application; 
import javafx.event.EventHandler; 

import javafx.scene.Group; 
import javafx.scene.PerspectiveCamera; 
import javafx.scene.Scene; 
import javafx.scene.control.TextField; 
import javafx.scene.input.KeyEvent; 
import javafx.scene.paint.Color; 
import javafx.scene.paint.PhongMaterial;
 
import javafx.scene.shape.Box; 
import javafx.scene.text.Font; 
import javafx.scene.text.FontWeight; 
import javafx.scene.text.Text;  
import javafx.scene.transform.Rotate; 
import javafx.stage.Stage; 
import javafx.util.Duration; 
         
public class EventHandlersExample extends Application { 
   
   @Override 
   public void start(Stage stage) {
      //Drawing a Box 
      Box box = new Box(); 
      
      //Setting the properties of the Box 
      box.setWidth(150.0); 
      box.setHeight(150.0);   
      box.setDepth(100.0); 
       
      //Setting the position of the box 
      box.setTranslateX(350);  
      box.setTranslateY(150); 
      box.setTranslateZ(50); 
       
      //Setting the text 
      Text text = new Text("Type any letter to rotate the box, 
         and click on the box to stop the rotation"); 
      
      //Setting the font of the text 
      text.setFont(Font.font(null, FontWeight.BOLD, 15));     
      
      //Setting the color of the text 
      text.setFill(Color.CRIMSON); 
      
      //setting the position of the text 
      text.setX(20); 
      text.setY(50); 
       
      //Setting the material of the box 
      PhongMaterial material = new PhongMaterial();  
      material.setDiffuseColor(Color.DARKSLATEBLUE);  
      
      //Setting the diffuse color material to box 
      box.setMaterial(material);       
       
      //Setting the rotation animation to the box    
      RotateTransition rotateTransition = new RotateTransition(); 
      
      //Setting the duration for the transition 
      rotateTransition.setDuration(Duration.millis(1000)); 
      
      //Setting the node for the transition 
      rotateTransition.setNode(box);       
      
      //Setting the axis of the rotation 
      rotateTransition.setAxis(Rotate.Y_AXIS); 
      
      //Setting the angle of the rotation
      rotateTransition.setByAngle(360); 
      
      //Setting the cycle count for the transition 
      rotateTransition.setCycleCount(50); 
      
      //Setting auto reverse value to false 
      rotateTransition.setAutoReverse(false);  
      
      //Creating a text filed 
      TextField textField = new TextField();   
      
      //Setting the position of the text field 
      textField.setLayoutX(50); 
      textField.setLayoutY(100); 
       
      //Handling the key typed event 
      EventHandler<KeyEvent> eventHandlerTextField = new EventHandler<KeyEvent>() { 
         @Override 
         public void handle(KeyEvent event) { 
            //Playing the animation 
            rotateTransition.play(); 
         }           
      };              
      //Adding an event handler to the text feld 
      textField.addEventHandler(KeyEvent.KEY_TYPED, eventHandlerTextField); 
       
      //Handling the mouse clicked event(on box) 
      EventHandler<javafx.scene.input.MouseEvent> eventHandlerBox = 
         new EventHandler<javafx.scene.input.MouseEvent>() { 
         
         @Override 
         public void handle(javafx.scene.input.MouseEvent e) { 
            rotateTransition.stop();  
         } 
      }; 
      //Adding the event handler to the box  
      box.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, eventHandlerBox);
       
      //Creating a Group object
      Group root = new Group(box, textField, text); 
         
      //Creating a scene object 
      Scene scene = new Scene(root, 600, 300);      
      
      //Setting camera 
      PerspectiveCamera camera = new PerspectiveCamera(false); 
      camera.setTranslateX(0); 
      camera.setTranslateY(0); 
      camera.setTranslateZ(0); 
      scene.setCamera(camera);  
      
      //Setting title to the Stage 
      stage.setTitle("Event Handlers Example"); 
         
      //Adding scene to the stage 
      stage.setScene(scene); 
         
      //Displaying the contents of the stage 
      stage.show(); 
   } 
   public static void main(String args[]){ 
      launch(args); 
   } 
}

Biên dịch và thực thi tệp java đã lưu từ dấu nhắc lệnh bằng các lệnh sau.

javac EventHandlersExample.java 
java EventHandlersExample

Khi thực thi, chương trình trên tạo một cửa sổ JavaFX hiển thị một trường văn bản và một hộp 3D như hình dưới đây:

Tại đây, nếu bạn nhập một ký tự vào trường văn bản, hộp 3D sẽ bắt đầu xoay dọc theo trục x. Nếu bạn nhấp vào hộp một lần nữa, vòng quay sẽ dừng lại.

Sử dụng các phương pháp thuận tiện để xử lý sự kiện

Một số lớp trong JavaFX xác định các thuộc tính của trình xử lý sự kiện. Bằng cách đặt các giá trị cho các thuộc tính này bằng các phương thức setter tương ứng của chúng, bạn có thể đăng ký một trình xử lý sự kiện. Những phương pháp này được gọi là phương pháp tiện lợi.

Hầu hết các phương thức này tồn tại trong các lớp như Node, Scene, Window, v.v. và chúng có sẵn cho tất cả các lớp con của chúng.

Ví dụ: để thêm trình nghe sự kiện chuột vào một nút, bạn có thể sử dụng phương pháp tiện lợi setOnMouseClicked() như hình bên dưới.

playButton.setOnMouseClicked((new EventHandler<MouseEvent>() { 
   public void handle(MouseEvent event) { 
      System.out.println("Hello World"); 
      pathTransition.play(); 
   } 
}));

Thí dụ

Chương trình sau đây là một ví dụ minh họa việc xử lý sự kiện trong JavaFX bằng các phương thức tiện lợi.

Lưu mã này trong một tệp có tên ConvinienceMethodsExample.java.

import javafx.animation.PathTransition; 
import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.event.EventHandler; 

import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.paint.Color; 

import javafx.scene.shape.Circle; 
import javafx.scene.shape.LineTo; 
import javafx.scene.shape.MoveTo; 
import javafx.scene.shape.Path; 
import javafx.stage.Stage; 
import javafx.util.Duration; 
         
public class ConvinienceMethodsExample extends Application { 
   @Override 
   public void start(Stage stage) {      
      //Drawing a Circle 
      Circle circle = new Circle(); 
      
      //Setting the position of the circle 
      circle.setCenterX(300.0f); 
      circle.setCenterY(135.0f); 
      
      //Setting the radius of the circle 
      circle.setRadius(25.0f);  
      
      //Setting the color of the circle 
      circle.setFill(Color.BROWN); 
      
      //Setting the stroke width of the circle 
      circle.setStrokeWidth(20);      
       
      //Creating a Path 
      Path path = new Path(); 
      
      //Moving to the staring point 
      MoveTo moveTo = new MoveTo(208, 71);               
      
      //Creating 1st line 
      LineTo line1 = new LineTo(421, 161);        
      
      //Creating 2nd line 
      LineTo line2 = new LineTo(226,232); 
      
      //Creating 3rd line 
      LineTo line3 = new LineTo(332,52);        
      
      //Creating 4th line 
      LineTo line4 = new LineTo(369, 250);        
      
      //Creating 5th line 
      LineTo line5 = new LineTo(208, 71);       
      
      //Adding all the elements to the path 
      path.getElements().add(moveTo); 
      path.getElements().addAll(line1, line2, line3, line4, line5);     
      
      //Creating the path transition 
      PathTransition pathTransition = new PathTransition(); 
      
      //Setting the duration of the transition 
      pathTransition.setDuration(Duration.millis(1000));       
      
      //Setting the node for the transition 
      pathTransition.setNode(circle); 
      
      //Setting the path for the transition 
      pathTransition.setPath(path); 
      
      //Setting the orientation of the path 
      pathTransition.setOrientation(
         PathTransition.OrientationType.ORTHOGONAL_TO_TAN GENT);
      
      //Setting the cycle count for the transition 
      pathTransition.setCycleCount(50); 
      
      //Setting auto reverse value to true 
      pathTransition.setAutoReverse(false);
      
      //Creating play button 
      Button playButton = new Button("Play"); 
      playButton.setLayoutX(300); 
      playButton.setLayoutY(250); 
       
      circle.setOnMouseClicked (new EventHandler<javafx.scene.input.MouseEvent>() { 
         @Override 
         public void handle(javafx.scene.input.MouseEvent e) { 
            System.out.println("Hello World"); 
            circle.setFill(Color.DARKSLATEBLUE);             
         } 
      });   
      playButton.setOnMouseClicked((new EventHandler<MouseEvent>() { 
         public void handle(MouseEvent event) { 
            System.out.println("Hello World");  
            pathTransition.play(); 
         } 
      })); 
       
      //Creating stop button 
      Button stopButton = new Button("stop"); 
      stopButton.setLayoutX(250); 
      stopButton.setLayoutY(250); 
      
      stopButton.setOnMouseClicked((new EventHandler<MouseEvent>() { 
         public void handle(MouseEvent event) { 
            System.out.println("Hello World"); 
            pathTransition.stop(); 
         } 
      }));
      //Creating a Group object  
      Group root = new Group(circle, playButton, stopButton); 
         
      //Creating a scene object 
      Scene scene = new Scene(root, 600, 300); 
      scene.setFill(Color.LAVENDER);  
      
      //Setting title to the Stage 
      stage.setTitle("Convenience Methods Example");  
         
      //Adding scene to the stage 
      stage.setScene(scene); 
         
      //Displaying the contents of the stage 
      stage.show(); 
   } 
   public static void main(String args[]){ 
      launch(args); 
   } 
}

Biên dịch và thực thi tệp java đã lưu từ dấu nhắc lệnh bằng các lệnh sau.

javac ConvinienceMethodsExample.java 
java ConvinienceMethodsExample

Khi thực thi, chương trình trên tạo một cửa sổ JavaFX như hình dưới đây. Tại đây nhấp vào nút play để bắt đầu hoạt ảnh và nhấp vào nút dừng để dừng hoạt ảnh.