按住按钮JavaFX的同时对多个节点进行MouseDragged检测

MouseDragged detection for multiple nodes while holding the button JavaFX

我就直说吧。我如何为我的应用程序实现一个系统,让我在按住鼠标左键的同时为下面显示的这些矩形着色?当释放时它停止着色。我通过互联网进行了搜索,但仍然不明白这些 MouseEvents 是如何工作的。

祝你有愉快的一天!

来自 javafx.scene.input.MouseEvent 的文档:

Dragging gestures

There are three types of dragging gestures. They are all initiated by a mouse press event and terminated as a result of a mouse released event, the source node decides which gesture will take place.

The simple press-drag-release gesture is default. It's best used to allow changing size of a shape, dragging it around and so on. Whole press-drag-release gesture is delivered to one node. When mouse button is pressed, the top-most node is picked and all subsequent mouse events are delivered to the same node until the button is released. If a mouse clicked event is generated from these events, it is still delivered to the same node.

During simple press-drag-release gesture, the other nodes are not involved and don't get any events. If these nodes need to be involved in the gesture, full press-drag-release gesture has to be activated. This gesture is best used for connecting nodes by "wires", dragging nodes to other nodes etc. This gesture type is more closely described at MouseDragEvent which contains the events delivered to the gesture targets.

The third gesture type is platform-supported drag-and-drop gesture. It serves best to transfer data and works also between (not necessarily FX) applications. This gesture type is more closely described at DragEvent.

In a short summary, simple press-drag-release gesture is activated automatically when a mouse button is pressed and delivers all MouseEvents to the gesture source. When you start dragging, eventually the DRAG_DETECTED event arrives. In its handler you can either start full press-drag-release gesture by calling startFullDrag method on a node or scene - the MouseDragEvents start to be delivered to gesture targets, or you can start drag and drop gesture by calling startDragAndDrop method on a node or scene - the system switches into the drag and drop mode and DragEvents start to be delivered instead of MouseEvents. If you don't call any of those methods, the simple press-drag-release gesture continues.

[...]

如果我对你的问题的理解正确,你希望能够将鼠标拖到多个节点上并让它们做出反应,所有这些都在一个手势中完成。您需要使用 full press-drag-release 手势来完成这个。如文档所述,您必须侦听 DRAG_DETECTED event and call Node#startFullDrag() or Scene#startFullDrag() to activate the full press-drag-release gesture. Then each "square" in your UI needs to listen for MOUSE_DRAG_ENTERED 事件。请注意,事件类型是 MOUSE_DRAG_ENTERED 而不是 MOUSE_ENTERED.

这是一个例子:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class App extends Application {

  @Override
  public void start(Stage primaryStage) {
    GridPane root = new GridPane();
    root.setPadding(new Insets(2));
    root.setVgap(2);
    root.setHgap(2);

    // start full press-drag-release gesture
    root.setOnDragDetected(
        event -> {
          if (event.getButton() == MouseButton.PRIMARY) {
            event.consume();
            root.startFullDrag();
          }
        });

    for (int i = 0; i < 12; i++) {
      for (int j = 0; j < 12; j++) {
        Rectangle rect = new Rectangle(50, 50, Color.WHITE);
        rect.setStroke(Color.BLACK);
        root.add(rect, i, j);

        // detect MOUSE_DRAG_ENTERED events
        rect.setOnMouseDragEntered(
            event -> {
              event.consume();
              rect.setFill(Color.BLACK);
            });
      }
    }

    primaryStage.setTitle("MouseDragEvent Example");
    primaryStage.setScene(new Scene(root));
    primaryStage.show();
  }
}

上面通过在根 GridPane 上设置 Node#onDragDetected 属性 来监听 DRAG_DETECTED 事件。请注意,如果您开始拖动 Rectangle 之一,则该事件将冒泡到根并由上述处理程序处理。此外,由于您明确提到了 left 鼠标按钮,因此我添加了一个检查鼠标按钮是否为主要按钮的功能。

然后每个 Rectangle 通过设置 Node#onMouseDragEntered 属性 来监听 MOUSE_DRAG_ENTERED 事件。仅当完全按下-拖动-释放 手势有效时,才会传递这些事件。