Łukasz Bocian
Łukasz Bocian

Reputation: 25

Rotation ImageView in JavaFX

I'm trying to do old radio knob with rotation and that rotation is my problem. When mouse cursor is on the knob- everything is okey, however when mouse is leaving knob area everything is working badly. Here is my code for knob.
EDIT: I want to rotate knob just by moving left and right. Up and down moves don't interest me.
EDIT2: The problem does not occur only in knob area. I think it is dependent on cursor travel distance.

@FXML
void onFrequencyKnobMouseMove(MouseEvent mouseEvent) {
    double vX = (mouseEvent.getX() - deltaX);
    System.out.println("VX: " + vX);

    double rotation = frequencyKnob.getRotate() + vX;
    if(rotation > 180) rotation=180;
    if(rotation < -180) rotation=-180;
    frequencyKnob.setRotate(rotation);
    System.out.println("ROTATION: " + rotation);

    tuningLine.setLayoutX(rotation*1.33+250);

    deltaX = mouseEvent.getX();
    System.out.println("DELTAX: " + deltaX + "\n\n");
}


@FXML
void onFrequencyKnobMouseDown(MouseEvent mouseEvent) {
    deltaX = mouseEvent.getX();
    //System.out.println(deltaX);
}

FXML file

<ImageView fx:id="frequencyKnob" layoutX="856.0" layoutY="29.0" onMouseDragged="#onFrequencyKnobMouseMove" onMousePressed="#onFrequencyKnobMouseDown">
    <image>
        <Image url="@knob.png" />
    </image>
</ImageView>

Knob rotating gif

Upvotes: 0

Views: 829

Answers (1)

fabian
fabian

Reputation: 82461

You added the handlers for the MouseEvents to the ImageView. The coordinates available via this event object are in the coordinate system of the ImageView which is rotated. You should instead use coordinates in a coordinate system that remains unmodified. The simplest way would be using the sceneX property instead of the x property of MouseEvent or by transforming to the coordinate system of the parent.

Example

@Override
public void start(Stage primaryStage) {
    Image image = new Image("knob.png");
    ImageView imageView = new ImageView(image);
    
    StackPane root = new StackPane(imageView);
    imageView.setPreserveRatio(true);
    imageView.setFitWidth(300);
    imageView.setFitHeight(300);
    
    Scene scene = new Scene(root, 500, 500);

    class MovedHandler implements EventHandler<MouseEvent> {
        
        double startX;
        double startRotate;
        
        @Override
        public void handle(MouseEvent event) {
            Point2D pt = imageView.localToParent(event.getX(), event.getY());
            double x = pt.getX();
            double newRotate = 3 * (x - startX) + startRotate;
            imageView.setRotate(newRotate);
        }
        
    }
    
    MovedHandler handler = new MovedHandler();
    imageView.setOnMouseDragged(handler);
    imageView.setOnMousePressed(event -> {
        Point2D pt = imageView.localToParent(event.getX(), event.getY());
        handler.startX = pt.getX();
        handler.startRotate = imageView.getRotate();
    });

    primaryStage.setScene(scene);
    primaryStage.show();
}

Upvotes: 2

Related Questions