5 votes

Comment dessiner une image avec une rotation sur un canevas JavaFX ?

Je veux dessiner une image sur le canevas avec une rotation. drawImage(image, 0, 0) Je peux dessiner une image mais comment puis-je faire pivoter cette image par exemple de 45 degrés et la dessiner, puis dessiner une autre image avec une rotation de -50 degrés sur le même canevas ?

graphicContext2D ne fonctionne pas pour moi car il fait pivoter tout le contenu du canevas.

19voto

jewelsea Points 40435

Voici un exemple, qui suit des principes similaires à la réponse de Katona, à la seule différence qu'il fait pivoter les images autour de points de pivot arbitraires en appliquant une transformation personnalisée.

rotatedimages

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.*;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

/** Rotates images round pivot points and places them in a canvas */
public class RotatedImageInCanvas extends Application {
    /**
     * Sets the transform for the GraphicsContext to rotate around a pivot point.
     *
     * @param gc the graphics context the transform to applied to.
     * @param angle the angle of rotation.
     * @param px the x pivot co-ordinate for the rotation (in canvas co-ordinates).
     * @param py the y pivot co-ordinate for the rotation (in canvas co-ordinates).
     */
    private void rotate(GraphicsContext gc, double angle, double px, double py) {
        Rotate r = new Rotate(angle, px, py);
        gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
    }

    /**
     * Draws an image on a graphics context.
     *
     * The image is drawn at (tlpx, tlpy) rotated by angle pivoted around the point:
     *   (tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2)
     *
     * @param gc the graphics context the image is to be drawn on.
     * @param angle the angle of rotation.
     * @param tlpx the top left x co-ordinate where the image will be plotted (in canvas co-ordinates).
     * @param tlpy the top left y co-ordinate where the image will be plotted (in canvas co-ordinates).
     */
    private void drawRotatedImage(GraphicsContext gc, Image image, double angle, double tlpx, double tlpy) {
        gc.save(); // saves the current state on stack, including the current transform
        rotate(gc, angle, tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2);
        gc.drawImage(image, tlpx, tlpy);
        gc.restore(); // back to original state (before rotation)
    }

    @Override public void start(Stage stage) {
        Image image = new Image(
            "http://worldpress.org/images/maps/world_600w.jpg", 350, 0, true, true
        );

        // creates a canvas on which rotated images are rendered.
        Canvas canvas = new Canvas(600, 400);
        GraphicsContext gc = canvas.getGraphicsContext2D();

        drawRotatedImage(gc, image,  40,   0,   0);
        drawRotatedImage(gc, image, -50, 400, 200);

        // supplies a tiled background image on which the canvas is drawn.
        StackPane stack = new StackPane();
        stack.setMaxSize(canvas.getWidth(), canvas.getHeight());
        stack.setStyle("-fx-background-image: url('http://1.bp.blogspot.com/_wV5JMD1OISg/TDYTYxuxR4I/AAAAAAAAvSo/a0zT8nwPV8U/s400/louis-vuitton-nice-beautiful.jpg');");
        stack.getChildren().add(
                canvas
        );

        // places a resizable padded frame around the canvas.
        StackPane frame = new StackPane();
        frame.setPadding(new Insets(20));
        frame.getChildren().add(stack);

        stage.setScene(new Scene(frame, Color.BURLYWOOD));
        stage.show();
    }

    public static void main(String[] args) { launch(RotatedImageInCanvas.class); }
}

4voto

Katona Points 2090

Je n'ai jamais utilisé JavaFX, mais en parcourant la documentation de son API, j'ai trouvé cette solution (je ne l'ai pas vraiment essayée, elle peut donc être erronée) :

Canvas canvas = ...
Image img = ...
GraphicsContext gc = canvas.getGraphicsContext2D();

gc.save(); // saves the current state on stack, including the current transform
gc.rotate(45);
gc.drawImage(img);
gc.restore(); // back to original state (before rotation)

gc.save();
gc.rotate(-50);
gc.drawImage(img);
gc.restore();

Je ne sais pas si cela fonctionne ici, mais l'idée (pile de transformation) est empruntée à d'autres API de dessin (comme OpenGL).

3voto

Le problème ci-dessus peut également être résolu en créant différentes couches de toile.

private void createLayers(){
        // Layers 1&2 are the same size
        layer1 = new Canvas(300,250);
        layer2 = new Canvas(300,250);

        // Obtain Graphics Contexts
        gc1 = layer1.getGraphicsContext2D();
        gc1.setFill(Color.GREEN);
        gc1.fillOval(50,50,20,20);
        gc1.getCanvas().setRotate(45);
        gc2 = layer2.getGraphicsContext2D();
        gc2.setFill(Color.BLUE);
        gc2.fillOval(100,100,20,20);
        gc.getCanvas().setRotate(135);
    }
        ...

 private void addLayers(){
        // Add Layers
        borderPane.setTop(cb);        
        Pane pane = new Pane();
        pane.getChildren().add(layer1);
        pane.getChildren().add(layer2);
        layer1.toFront();
        borderPane.setCenter(pane);    
        root.getChildren().add(borderPane);
    }

0voto

Thorsten Points 143

Je rencontrais des problèmes similaires avec les ImageViews, après avoir fait pivoter et mis à l'échelle une image, celle-ci n'était pas dimensionnée correctement par les gestionnaires de mise en page des conteneurs parents.

Selon les idées présentées ici, j'ai créé un ImageCanvas qui reflète la dimension de l'image rendue, qu'elle soit tournée ou mise à l'échelle.

Voir https://github.com/treimers/JfxImageCanvas

Appréciez Thorsten

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X