How could I implement a system for my application that lets me color these rectangles showed below, while holding left mouse button? And when released it stops coloring. I searched trough the internet but I still can't understand how do those MouseEvents work.
From the documentation of 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
MouseEvent
s to the gesture source. When you start dragging, eventually theDRAG_DETECTED
event arrives. In its handler you can either start full press-drag-release gesture by callingstartFullDrag
method on a node or scene - theMouseDragEvent
s start to be delivered to gesture targets, or you can start drag and drop gesture by callingstartDragAndDrop
method on a node or scene - the system switches into the drag and drop mode andDragEvent
s start to be delivered instead ofMouseEvent
s. If you don't call any of those methods, the simple press-drag-release gesture continues.[...]
If I understand your question correctly, you want to be able to drag the mouse over multiple nodes and have them react, all in one gesture. You'll want to use a full
press-drag-release gesture to accomplish this. As documented, you have to listen for a 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
events. Notice that the event type is MOUSE_DRAG_ENTERED
and not MOUSE_ENTERED
.
Here's an example:
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();
}
}
The above listens for DRAG_DETECTED
events by setting the Node#onDragDetected
property on the root GridPane
. Note that if you start dragging on one of the Rectangle
s then the event will bubble up to the root and be handled by the aforementioned handler. Also, since you explicitly mention the left mouse button I added a check for if the mouse button is the primary or not.
Then each Rectangle
listens for MOUSE_DRAG_ENTERED
events by having their Node#onMouseDragEntered
property set. These events will only be delivered if a full press-drag-release gesture is in effect.