Paintable Canvas Hacks

I've been playing around with the paintable canvas quite a bit here lately for fun, and I was wondering if anybody had any cool hacks for canvas development they would be willing to share.

To start things off, I'll share a simple way to get curves right in the canvas.

Using variable names that are self explanitory, the drawArc method looks like this:

g.drawArc(x, y, width, height, startingAngle, angleLengthInDegrees)

I've found that if you take the circle tool, give it a transparent background, and position it where you want the curve to be, its x, y, width and height parameters will be exactly right.

Therefore. if I wanted to make something like this custom gauge with rounded edges:

I could start by simply overlaying my canvas with simple shapes produced by the round shape tool to get the proper dimensions:


Then, select each shape and press ctrl-P to get the parameters:
In my case, the bounds for the four circles are:

[46, 221, 50, 50] # Left small circle
[204, 221, 50, 50] # Right small circle
[50, 50, 200, 200] # Large inner circle
[0, 0, 300, 300] # Large outer circle

Once this is done there will only be two parameters needed for each of the four arcs. This can be determined by simply using a unit circle:

It looks like my two large circles should start at about 315 degrees and end at around 225 degrees. That would be a total of 270 degrees travel, so my code would look like this:

g =

g.drawArc(0, 0, 300, 300, 315, 270)
g.drawArc(50, 50, 200, 200, 315, 270)

Looking again at the unit circle, I can estimate that my small left circle should start at around 225 degrees and end 180 degrees later at 45 degrees. My right small circle looks like it should start at around 135 degrees, and end 180 degrees later at 315 degrees, so I'll add these lines to my code:

g.drawArc(46, 221, 50, 50, 225, 180)
g.drawArc(204, 221, 50, 50, 135, 180)

When I run preview mode, I see this in my canvas:

It's not perfect, but it's pretty darn close. From here, a little trial and error to tweak the numbers produces this result:

g =

# Large Outer Circle
g.drawArc(0, 0, 300, 300, 310, 280)

# Large Inner Circle
g.drawArc(50, 50, 200, 199, 309, 283)

# Small Left Arc
g.drawArc(46, 221, 51, 51, 228, 180)

# Small Right Arc
g.drawArc(204, 221, 50, 50, 130, 180)

This is how I did it a few years ago...
GaugeArcDonutAnimation (23.5 KB)
I'm using Arc2D.Double with g.setStroke(BasicStroke(arcwidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)).
CAP_ROUND is for rounded ends, CAP_BUTT is for normal ends...