# Percent Fill Basic Shape

**URL:** <https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547>\
**Category:** Ignition\
**Tags:** ignition81, vision\
**Created:** [December 1, 2025, 10:15pm UTC](https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547 "2025-12-01T22:15:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [December 1, 2025, 10:15pm UTC](https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547/1 "2025-12-01T22:15:35Z")

</div>

Working with vision, I have a basic circle shape and I want to fill a certain portion of the inside based on a value. For instance, half full at 50%.

Is there an easy way to do this?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [December 1, 2025, 10:24pm UTC](https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547/2 "2025-12-01T22:24:48Z")

</div>

Use the Paintable Canvas.  
E.G:

> **[Ignition Exchange](https://inductiveautomation.com/exchange/2038/overview)**
>
> Discover, share, and download community made Ignition resources in collaboration with your organization or the Ignition community.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [December 1, 2025, 10:55pm UTC](https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547/3 "2025-12-01T22:55:46Z")

</div>

When I import that it has an issue with the parent project. I suppose that doesn’t really matter though as all I need is the script. Thanks

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [December 1, 2025, 10:59pm UTC](https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547/4 "2025-12-01T22:59:04Z")

</div>

Exchange resources are packaged up weird. Inside the downloaded zip there's another zip that contains the 'raw' project export, which should import fine into 8.1... guess I gotta make a new version for 8.3, since you won't be able to import the 8.0 project.

EDIT: Actually, I think it'll still import fine to 8.3, it's just gateway restore we don't support, but project restoration should be fine.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [December 2, 2025, 2:13pm UTC](https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547/5 "2025-12-02T14:13:46Z")

</div>

Does the designer ever show anything in the paintable canvas, or only in runtime?

How would I hardcode a java color in the script? I just want the circle to have a transparent background where not filled.

I also get an error “object has no attribute `drawCenteredString`” - I could easily just add text on top of the paintable canvas

```python
from java.awt import BasicStroke
from java.awt.geom import Area, Ellipse2D, Rectangle2D

g = event.graphics

w = event.source.parent.width-2
h = event.source.parent.height-2

backgroundColor = event.source.background
foregroundColor = event.source.foreground

state = event.source.parent.state

#pump is running, show speed as needed
if 1 == state:
	level = event.source.parent.fillLevel
	show = event.source.parent.showLevel
#pump is not running or failed, don't show speed and fully fill
else:
	level = 100
	show = False

# Create shapes
circle = Ellipse2D.Float(1, 1, w, h)
fillLevel = min(100, level)
clip = Rectangle2D.Float(1, 1, w, h - level)

# Set line width
g.setStroke(BasicStroke(0.2))

# Draw transparent circle background
g.setColor(event.source.parent.background)
g.fill(circle)

# Draw partially filled circle
g.setColor(backgroundColor)
fill = Area(circle)
fill.subtract(Area(clip))
g.fill(fill)

# Draw circle outline
g.setColor(foregroundColor)
g.draw(circle)

# Draw % fill
if show:
	event.source.drawCenteredString("%s%%" % float(level)/10.0, w, h, g)

```

---

<div class="post-metadata">

**Author:** ![MMaynard](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mmaynard/32/3366_2.png) [@MMaynard](https://forum.inductiveautomation.com/u/MMaynard)\
**Post date:** [December 2, 2025, 2:30pm UTC](https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547/6 "2025-12-02T14:30:48Z")

</div>

For something simpler you can just “mask” a level indicator with a rectangle cut out.

Draw a rectangle, draw a circle, center them on each other.

Select the rectangle and circle, click the Difference button.

Then drag a level indicator on to the window and arrange them, setting the new shape background color to match the window background color and border to transparent.

 ![Screenshot 2025-12-02 092641](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/0/500499238aecbd04e966ea08a78fdf19d7548849.png)

 ![Screenshot 2025-12-02 092710](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/1/d179175105c5e2c1429a1c05b3957db03ba4c563.png)

 ![Screenshot 2025-12-02 092700](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/4/a4eddaf41537edbfa2166895ea9c373a0514334b.png)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [December 2, 2025, 4:23pm UTC](https://forum.inductiveautomation.com/t/percent-fill-basic-shape/112547/7 "2025-12-02T16:23:47Z")

</div>

> [@amarks](#):
>
> Does the designer ever show anything in the paintable canvas, or only in runtime?

Nothing at 'design' time, but the component will render in 'preview' mode.

> [@amarks](#):
>
> How would I hardcode a java color in the script?

`system.gui.color` (`system.vision.color` in 8.3).

> [@amarks](#):
>
> I also get an error “object has no attribute `drawCenteredString`” - I could easily just add text on top of the paintable canvas

`drawCenteredString` is a custom method on the template:

```python
def drawCenteredString(self, text, width, height, graphics):
	"""
	Arguments:
		self: A reference to the component instance this method is invoked on. This argument
		  is automatic and should not be specified when invoking this method.
	"""
	fm = graphics.fontMetrics
	offsetX = (width - fm.stringWidth(text)) / 2
	offsetY = (fm.ascent + (height - (fm.ascent + fm.descent)) / 2)
	graphics.drawString(text, offsetX, offsetY)

```
