I'm trying to write a painting application in JavaFX. I want a brush resembling a real paintbrush, but I'm not sure how to start the algorithm. The code below shows my current paintbrush stroke, although it's a useful stroke, it's not really a paintbrush:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
import javafx.stage.Stage;
import static javafx.scene.input.MouseEvent.*;
public class BrushTester extends Application {
private static final Color color = Color.CHOCOLATE;
private static final double START_OPACITY = 0.3;
private static final double OPACITY_MODIFIER = 0.002;
private double currentOpacity = START_OPACITY;
private double strokeWidth = 15;
public static void main(String[] args) {
Application.launch(BrushTester.class);
}
@Override
public void start(Stage primaryStage) throws Exception {
Canvas canvas = new Canvas(600d, 600d);
GraphicsContext gc = canvas.getGraphicsContext2D();
canvas.addEventHandler(MOUSE_DRAGGED, e -> BrushTester.this.handleMouseDragged(gc, e));
canvas.addEventHandler(MOUSE_PRESSED, e -> handleMousePressed(gc, e));
canvas.addEventHandler(MOUSE_RELEASED, e -> handleMouseReleased(gc, e));
Group root = new Group();
root.getChildren().add(canvas);
primaryStage.setScene(new Scene(root, Color.DARKGRAY));
primaryStage.show();
}
private void configureGraphicsContext(GraphicsContext gc) {
gc.setStroke(new Color(color.getRed(), color.getGreen(), color.getBlue(), currentOpacity));
gc.setLineCap(StrokeLineCap.ROUND);
gc.setLineJoin(StrokeLineJoin.ROUND);
gc.setLineWidth(strokeWidth);
}
public void handleMousePressed(GraphicsContext gc, MouseEvent e) {
configureGraphicsContext(gc);
gc.beginPath();
gc.moveTo(e.getX(), e.getY());
gc.stroke();
}
public void handleMouseReleased(GraphicsContext gc, MouseEvent e) {
currentOpacity = START_OPACITY;
gc.closePath();
}
public void handleMouseDragged(GraphicsContext gc, MouseEvent e) {
currentOpacity = Math.max(0, currentOpacity - OPACITY_MODIFIER);
configureGraphicsContext(gc);
gc.lineTo(e.getX(), e.getY());
gc.stroke();
}
}
Anyone with some tips on how to get closer to the real thing?
It all depends on what you're trying to achieve. Personally I would use
A quick example with a simple drawing algorithm:
Of course you can extend this with e. g.
Example with Brush variations when you start painting:
Example with variation for limiting the brush length
This is how it looks like:
or using different colors, I added a color picker in the last example: