javafxgraphics2dfillgraphicscontext

JavaFX - draw donut


I need to draw a donut shape using JavaFX's GraphicsContext - a filled circle with a hole in the center, to clarify.

I have been searching and I can't find any examples online.

I think you'd use the fillarc function, but I do not understand it. There are no examples that I could find, and the docs do not help much. (What is arcExtent? All the docs say is that it's the extent of the arc...)

I don't want to fill two overlapping circles, because I want to keep the center transparent while drawing. (I have already drawn stuff underneath, I can't interfere with it)


Solution

  • Here are a couple of sample solutions, one uses shape subtraction for circles, another uses an Arc. Both examples use the scene graph for drawing.

    sample

    import javafx.application.Application;
    import javafx.scene.*;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.*;
    import javafx.stage.Stage;
    
    public class DonutHole extends Application {
        @Override
        public void start(Stage stage) throws Exception {
            // donut by shape subtraction.
            Circle whole = new Circle(20, 20, 20);
            Circle inside = new Circle(20, 20, 10);
            Shape donutShape = Shape.subtract(whole, inside);
            donutShape.setFill(Color.BLUE);
    
            // donut by arc.
            Arc donutArc = new Arc(60, 20, 10, 10, 0, 360);
            donutArc.setStrokeWidth(10);
            donutArc.setStrokeType(StrokeType.OUTSIDE);
            donutArc.setStroke(Color.RED);
            donutArc.setStrokeLineCap(StrokeLineCap.BUTT);
            donutArc.setFill(null);
    
            Scene scene = new Scene(new Group(donutShape, donutArc), Color.PALEGREEN);
            stage.setScene(scene);
            stage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    An alternate solution could also use a Path with arc and line segments, but I don't show that here. If you wanted a 3D donut, you could create a Torus.


    Here is another example which uses fillArc in a GraphicsContext.

    fill

    import javafx.application.Application;
    import javafx.scene.*;
    import javafx.scene.canvas.*;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.*;
    import javafx.stage.Stage;
    
    public class DonutHoleGraphics extends Application {
        @Override
        public void start(Stage stage) throws Exception {
            Canvas canvas = new Canvas(40, 40);
    
            GraphicsContext gc = canvas.getGraphicsContext2D();
            gc.setLineWidth(10);
            gc.setStroke(Color.YELLOW);
            gc.setLineCap(StrokeLineCap.BUTT);
            gc.strokeArc(5, 5, 30, 30, 0, 360, ArcType.OPEN);
    
            Scene scene = new Scene(new Group(canvas), Color.PALEGREEN);
            stage.setScene(scene);
            stage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    Related: