在按住按钮JavaFX的同时对多个节点进行鼠标拖动检测
我将直接回答这个问题。我如何为我的应用程序实现一个系统,让我在按住鼠标左键的同时为下面显示的这些矩形上色?当它被释放时,它就会停止着色。我通过互联网搜索了一下,但我仍然不明白这些鼠标事件是如何工作的。
祝你有愉快的一天!
解决方案
来自javafx.scene.input.MouseEvent
的文档:
如果我正确理解了您的问题,您希望能够将鼠标拖动到多个节点上并让它们做出反应,所有操作都在一个手势中完成。您将需要使用完整的 按下-拖动-释放手势即可完成此操作。如前所述,您必须侦听拖动手势
有三种类型的拖动手势。它们都是由鼠标按下事件启动的,并由于鼠标释放事件而终止,源节点决定将发生哪个手势。 默认设置为简单的按下-拖动-释放手势。它最适合用于更改形状的大小、拖动形状等等。整个按下-拖动-释放手势被传递到一个节点。按下鼠标按钮时,将拾取最顶端的节点,并将所有后续鼠标事件传递到同一节点,直到释放该按钮。如果鼠标单击事件是从这些事件生成的,它仍会传递到同一节点。在简单的按下拖动释放手势期间,其他节点不会参与,也不会获得任何事件。如果这些节点需要参与手势,则必须激活完整的按下-拖动-释放手势。此手势最适合用于通过"Wire"连接节点、将节点拖动到其他节点等。
第三种手势类型是平台支持的拖放手势。它最适合于传输数据,也适用于应用程序之间(不一定是FX)。此手势类型在MouseDragEvent
中对此手势类型的描述更为详细,它包含传递到手势目标的事件。DragEvent
中有更详细的描述。 简而言之,当按下鼠标按键时,会自动激活简单的按下拖动释放手势,并将所有MouseEvent
发送到手势源。当您开始拖动时,DRAG_DETECTED
事件最终会到达。在其处理程序中,您可以通过在节点或场景上调用startFullDrag
方法来启动完整的按拖放手势--MouseDragEvent
开始传递到手势目标,或者您可以通过在节点或场景上调用startDragAndDrop
方法来开始拖放手势-系统切换到拖放模式,DragEvent
开始传递,而不是MouseEvent
。如果您不调用这些方法中的任何一个,则简单的按拖放手势将继续。[...]
DRAG_DETECTED
事件并调用Node#startFullDrag()
或Scene#startFullDrag()
以激活完全按下-拖动-释放手势。然后,您的用户界面中的每个"正方形"都需要侦听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
上拖动,则事件将向上冒泡到根,并由前面提到的处理程序处理。此外,由于您明确提到了左鼠标按键,因此我添加了鼠标按键是否为主按键的检查。
然后,每个Rectangle
通过设置其Node#onMouseDragEntered
属性来侦听MOUSE_DRAG_ENTERED
事件。仅当完全按下-拖动-释放手势生效时,才会传递这些事件。
相关文章