JavaFX Tip 2: Sharp Drawing with Canvas API

When I initially started out working with the Canvas API I noticed that the results of my rendering code were somewhat blurry and even worse, inconsistent. Some lines were blurry, others sharp. Coming from Swing it took me some time to realize that this was caused by the coordinate system of JavaFX, which allows for double precision rendering.
To solve this problem all that is needed is to use coordinates “in the middle”. So in my code you now find a lot of methods called snapXZY() (similar methods can be found in the JavaFX code itself), which first casts the given coordinate to an integer and then adds .5 to it. The following screenshot shows the difference when using this approach.
 
 
bildschirmfoto-2014-04-10-um-11-59-49
The code below was used for this example:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/**
 * Tip 2: How to render sharp lines in a canvas.
 */
public class Tip2DrawingSharpLinesInCanvas extends 
        Application {

	class MyCanvas extends Canvas {

		public MyCanvas(boolean drawSharpLines) {

			setWidth(150);
			setHeight(150);

			double w = getWidth();
			double h = getHeight();

			GraphicsContext gc = getGraphicsContext2D();
			gc.clearRect(0, 0, w, h);

			gc.setStroke(Color.GRAY);
			gc.strokeRect(0, 0, w, h);

			for (double y = 20; y <= h - 20; y += 10) {
				if (drawSharpLines) {
					// Snap the y coordinate 
					gc.strokeLine(10, 
                                   snap(y), 
                                   w - 10, 
                                   snap(y));
				} else {
					gc.strokeLine(10, y, w - 10, y);
				}
			}
		}

		private double snap(double y) {
			return ((int) y) + .5;
		}
	}

	@Override
	public void start(Stage stage) throws Exception {
		MyCanvas canvasBlurry = new MyCanvas(false);
		MyCanvas canvasSharp = new MyCanvas(true);

		Label labelBlurry = new Label("Blurry");
		Label labelSharp = new Label("Sharp");

		VBox.setMargin(canvasBlurry, new Insets(10));
		VBox.setMargin(canvasSharp, new Insets(10));

		VBox.setMargin(labelBlurry, 
                     new Insets(10, 10, 0, 10));
		VBox.setMargin(labelSharp, 
                     new Insets(10, 10, 0, 10));

		VBox box = new VBox();
		box.getChildren().add(labelBlurry);
		box.getChildren().add(canvasBlurry);
		box.getChildren().add(labelSharp);
		box.getChildren().add(canvasSharp);

		stage.setScene(new Scene(box));
		stage.setTitle("Tip 2: Sharp Lines in Canvas");
		stage.show();
	}

	public static void main(String[] args) {
		launch(args);
	}
}
Reference: JavaFX Tip 2: Sharp Drawing with Canvas API from our JCG partner Dirk Lemmermann at the Pixel Perfect blog.
Related Whitepaper:

Java Essential Training

Author David Gassner explores Java SE (Standard Edition), the language used to build mobile apps for Android devices, enterprise server applications, and more!

The course demonstrates how to install both Java and the Eclipse IDE and dives into the particulars of programming. The course also explains the fundamentals of Java, from creating simple variables, assigning values, and declaring methods to working with strings, arrays, and subclasses; reading and writing to text files; and implementing object oriented programming concepts. Exercise files are included with the course.

Get it Now!  

One Response to "JavaFX Tip 2: Sharp Drawing with Canvas API"

  1. Very nice – this is the second time today I’ve accidentally hit a blog of yours that informed me on something that was timely and useful. Look at the blurry lines on my last blog post: http://reportmill.files.wordpress.com/2014/04/showcoords.jpg . I’ll fix that using your suggestion – thanks!

Leave a Reply


5 × three =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books