问题
I want the user to be able to drag-move the circles around the pane. The circles dont seem to register (almost) no mouse events (as defined in the end). I have the same exact code for an empty pane it works just fine. Also if I change
circle1.setOnMouseDragged
to
paneForCircles.setOnMouseDragged
it works just fine but its not what I want because I need to manipulate both circles. Any ideas ? I would appreciate it if you could also tell me how to hide the part of the circle that overlaps with the adjacent elements if its center is too close to the pane border.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Ex168 extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Circle circle1 = new Circle(30);
Circle circle2 = new Circle(35);
circle1.setCenterX(100);
circle1.setCenterY(100);
circle2.setCenterX(150);
circle2.setCenterY(120);
circle1.setStroke(Color.BLACK);
circle1.setFill(null);
circle2.setStroke(Color.BLACK);
circle2.setFill(null);
VBox vBoxForScene = new VBox(5);
vBoxForScene.setPadding(new Insets(5));
vBoxForScene.setAlignment(Pos.TOP_CENTER);
Pane paneForCircles = new Pane();
paneForCircles.setStyle("-fx-border-color: black");
vBoxForScene.heightProperty().addListener(ov -> paneForCircles.setPrefHeight(vBoxForScene.heightProperty().divide(1.2).doubleValue()));
paneForCircles.setPrefHeight(300);
HBox hBoxForFields = new HBox(5);
hBoxForFields.setAlignment(Pos.CENTER);
hBoxForFields.setSpacing(5);
// VBofForLeftFields
VBox vBoxForLeftFields = new VBox(5);
vBoxForLeftFields.setAlignment(Pos.CENTER_LEFT);
Label lblCircle1 = new Label("Enter Circle 1 info");
lblCircle1.setAlignment(Pos.TOP_LEFT);
TextField tfCircle1CenterX = new TextField();
tfCircle1CenterX.textProperty().bind(circle1.centerXProperty().asString());
TextField tfCircle1CenterY = new TextField();
tfCircle1CenterY.textProperty().bind(circle1.centerYProperty().asString());
TextField tfCircle1Radius = new TextField();
tfCircle1Radius.textProperty().bind(circle1.radiusProperty().asString());
tfCircle1CenterX.setPrefColumnCount(5);
tfCircle1Radius.setPrefColumnCount(5);
tfCircle1CenterY.setPrefColumnCount(5);
Label lblCenterX = new Label("Center x:", tfCircle1CenterX);
Label lblCenterY = new Label("Center x:", tfCircle1CenterY);
Label lblCircle1Radius= new Label("Radius: ", tfCircle1Radius);
lblCenterX.setContentDisplay(ContentDisplay.RIGHT);
lblCenterY.setContentDisplay(ContentDisplay.RIGHT);
lblCircle1Radius.setContentDisplay(ContentDisplay.RIGHT);
//VBoxForRightFields
VBox vBoxForRightFields = new VBox(5);
Label lblCircle2 = new Label("Enter Circle 2 info");
TextField tfCircle2CenterX = new TextField();
TextField tfCircle2CenterY = new TextField();
TextField tfCircle2Radius = new TextField();
tfCircle2CenterX.setPrefColumnCount(5);
tfCircle2CenterX.textProperty().bind(circle2.centerXProperty().asString());
tfCircle2Radius.setPrefColumnCount(5);
tfCircle2Radius.textProperty().bind(circle2.radiusProperty().asString());
tfCircle2CenterY.setPrefColumnCount(5);
tfCircle2CenterY.textProperty().bind(circle2.centerYProperty().asString());
Label lblCenter2X = new Label("Center x:", tfCircle2CenterX);
Label lblCenter2Y = new Label("Center x:", tfCircle2CenterY);
Label lblCircle2Radius= new Label("Radius: ", tfCircle2Radius);
lblCenter2X.setContentDisplay(ContentDisplay.RIGHT);
lblCenter2Y.setContentDisplay(ContentDisplay.RIGHT);
lblCircle2Radius.setContentDisplay(ContentDisplay.RIGHT);
vBoxForRightFields.getChildren().addAll(lblCircle2, lblCenter2X, lblCenter2Y, lblCircle2Radius);
vBoxForLeftFields.getChildren().addAll(lblCircle1, lblCenterX, lblCenterY, lblCircle1Radius);
hBoxForFields.getChildren().addAll(vBoxForLeftFields, vBoxForRightFields);
Label lblResult = new Label("Do the two circles intersect?");
Button btReDrawCircles = new Button("Redraw Circles");
vBoxForScene.getChildren().addAll(lblResult, paneForCircles, hBoxForFields, btReDrawCircles);
circle1.setOnMouseDragged(e -> {
System.out.println(e.getX());
circle1.setCenterX(e.getX());
circle1.setCenterY(e.getY());
});
circle2.setOnMouseDragged(e -> {
circle2.setCenterX(e.getX());
circle2.setCenterY(e.getY());
});
paneForCircles.getChildren().addAll(circle1, circle2);
Scene scene = new Scene(vBoxForScene);
primaryStage.setScene(scene);
primaryStage.setMinHeight(400);
primaryStage.setMinWidth(340);
primaryStage.setAlwaysOnTop(true);
primaryStage.show();
circle1.requestFocus();
}
}
This code on the other hand, which is supposed to do the same thing, works perfectly
public class CircleDraggingSample extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
final double RADIUS=10;
Pane pane = new Pane();
pane.setPrefHeight(300);
pane.setPrefWidth(300);
Circle circle1 = new Circle(RADIUS);
circle1.setCenterX(30);
circle1.setCenterY(30);
Circle circle2 = new Circle(RADIUS);
circle2.setCenterX(100);
circle2.setCenterY(100);
Line line = new Line();
line.endXProperty().bind(circle2.centerXProperty());
line.endYProperty().bind(circle2.centerYProperty());
line.startXProperty().bind(circle1.centerXProperty());
line.startYProperty().bind(circle1.centerYProperty());
pane.getChildren().addAll(circle1, circle2, line);
circle2.setOnMouseDragged(e -> {
circle2.setCenterX(e.getX());
circle2.setCenterY(e.getY());
});
circle1.setOnMouseDragged(e -> {
circle1.setCenterX(e.getX());
circle1.setCenterY(e.getY());
});
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
回答1:
Even though you have posted an example, I'd rather show you a way with mine how it is done in general. There are several ways, this is one that works:
public class DragNodes extends Application {
public static List<Circle> circles = new ArrayList<Circle>();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Circle circle1 = new Circle( 100, 100, 50);
circle1.setStroke(Color.GREEN);
circle1.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.3));
Circle circle2 = new Circle( 200, 200, 50);
circle2.setStroke(Color.BLUE);
circle2.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.3));
Line line = new Line();
line.setStrokeWidth(20);
// binding
line.startXProperty().bind(circle1.centerXProperty());
line.startYProperty().bind(circle1.centerYProperty());
line.endXProperty().bind(circle2.centerXProperty());
line.endYProperty().bind(circle2.centerYProperty());
MouseGestures mg = new MouseGestures();
mg.makeDraggable( circle1);
mg.makeDraggable( circle2);
mg.makeDraggable( line);
root.getChildren().addAll(circle1, circle2, line);
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.show();
}
public static class MouseGestures {
class DragContext {
double x;
double y;
}
DragContext dragContext = new DragContext();
public void makeDraggable( Node node) {
node.setOnMousePressed( onMousePressedEventHandler);
node.setOnMouseDragged( onMouseDraggedEventHandler);
node.setOnMouseReleased(onMouseReleasedEventHandler);
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if( event.getSource() instanceof Circle) {
Circle circle = ((Circle) (event.getSource()));
dragContext.x = circle.getCenterX() - event.getSceneX();
dragContext.y = circle.getCenterY() - event.getSceneY();
} else {
Node node = ((Node) (event.getSource()));
dragContext.x = node.getTranslateX() - event.getSceneX();
dragContext.y = node.getTranslateY() - event.getSceneY();
}
}
};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if( event.getSource() instanceof Circle) {
Circle circle = ((Circle) (event.getSource()));
circle.setCenterX( dragContext.x + event.getSceneX());
circle.setCenterY( dragContext.y + event.getSceneY());
} else {
Node node = ((Node) (event.getSource()));
node.setTranslateX( dragContext.x + event.getSceneX());
node.setTranslateY( dragContext.y + event.getSceneY());
}
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
}
};
}
}
It shows how to drag circles and bind another node (the line) so that it gets modified as well when you drag the circles. You can also drag the line separately which is a Node and handled differently.
In case you still got problems let me know.
As a general note, it's always advisable to add this to a node in order to understand which events happen:
node.addEventFilter(Event.ANY, e -> System.out.println( e));
and then check the console output while you do something on screen.
Regarding your main problem: You mustn't set Fill to null. In that case the click event won't get registered. You should use Color.TRANSPARENT instead. You can verify the event difference with the above mentioned method.
来源:https://stackoverflow.com/questions/29394632/javafx-circle-object-not-registering-mouse-events-properly