# Rotating graphic is changing sizes at random

**URL:** <https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822>\
**Category:** Ignition\
**Tags:** vision, ignition81\
**Created:** [March 30, 2023, 12:33pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822 "2023-03-30T12:33:52Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [May 4, 2023, 1:22pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/21 "2023-05-04T13:22:56Z")

</div>

Honestly, if I were going to do this, I would use a paintable canvas and draw the entire thing.

Here is an example from sometime ago that does something similar (although I don't think you need to deal with the mouse), perhaps it can provide some insight.

> [@Circular Slider in canvas](https://forum.inductiveautomation.com/t/circular-slider-in-canvas/26254/2):
>
> Had to brush up on my Vector Algebra to get it, but the below code will accomplish what I believe you are wanting. I was unable to use your project file as I believe you have a newer version than I do. Hopefully the following will help get you where your trying to go. I added the following custom properties to the Paintable Canvas object: value - stores the current unscaled angle of the slider button length - a value from 20 to 359 degrees ( I force the limits in the propertyChange event, an…

Maybe, I will throw something together later today if I get a chance.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [May 4, 2023, 1:33pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/22 "2023-05-04T13:33:03Z")

</div>

> [@lrose](#):
>
> I would use a paintable canvas

That sounds like a sensible approach.

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/e/de25dfb6233713f7a07586ecf360191f6a8d1f26.png)  
...and by the way, these things are beautiful. I'm definitely going to lose some of my time off this weekend finding uses for this type of slider.

I'm looking forward to seeing the timer component you come up with.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [May 4, 2023, 1:35pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/23 "2023-05-04T13:35:42Z")

</div>

> [@justinedwards.jle](#):
>
> I'm definitely going to lose some of my time off this weekend finding uses for this type of slider.

You might loose quite a bit of time fixing the bug I never got around to fixing. 🤣

---

<div class="post-metadata">

**Author:** ![steven.rehnborg](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/steven.rehnborg/32/4952_2.png) [@steven.rehnborg](https://forum.inductiveautomation.com/u/steven.rehnborg)\
**Post date:** [May 5, 2023, 7:45pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/24 "2023-05-05T19:45:55Z")

</div>

I like your solution. very elegant. I hope to try it out when I have a chance!

---

<div class="post-metadata">

**Author:** ![steven.rehnborg](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/steven.rehnborg/32/4952_2.png) [@steven.rehnborg](https://forum.inductiveautomation.com/u/steven.rehnborg)\
**Post date:** [May 5, 2023, 7:50pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/25 "2023-05-05T19:50:05Z")

</div>

I gave up on dynamically changing the angle of the "hand" object. I've redone it with a simple bitmap of a line and dynamically changing the rotation of the image.

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/8/c8e44571394bd1d5813b02d9830b82ea8605db92.png)

I'd still like to know the issue with the former. IRose, I like your solution, but this keeps it within the K.I.S.S. philosophy (my version: Keep It Simple Steve).

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [May 5, 2023, 9:05pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/26 "2023-05-05T21:05:16Z")

</div>

Well if you want it, here is what I threw together. You of course can add more customization if needed or wanted.

> **repaint script**
>
> ```auto
> from java.awt import Color
> from java.awt import RadialGradientPaint
> from java.awt import MultipleGradientPaint as mgp
> from java.awt.geom import Rectangle2D
> from java.awt.geom import Ellipse2D
> from java.awt.geom import Line2D
> from java.awt.geom import Point2D
> from java.awt import BasicStroke
> from java.awt.geom import Path2D
> import math
> g = event.graphics
> 
> #Watch Body
> 
> bodyOutline = Ellipse2D.Float(event.width * .075, event.height * .115, event.width * .85, event.height * .85)
> bodyShape = Ellipse2D.Float(event.width * .1 ,event.height * .14 , event.width * .8, event.height * .8)
> cX = bodyShape.getX() + bodyShape.getWidth() / 2
> cY = bodyShape.getY() + bodyShape.getHeight() / 2
> radius = bodyShape.width / 2
> 
> #Draw outside
> g.setStroke(BasicStroke(1.0))
> g.setPaint(Color.BLACK)
> g.draw(bodyOutline)
> 
> center = Point2D.Float(cX,cY)
> focus = Point2D.Float((radius - 10) * math.cos(math.pi / 4) + cX,(radius - 10) * math.sin(math.pi / 4) + cY)
> colors = [Color.WHITE,Color.LIGHT_GRAY,Color.GRAY]
> bodyPaint = RadialGradientPaint(center,300,focus, [0.0,0.8,1.0],colors,mgp.CycleMethod.NO_CYCLE)
> g.setPaint(bodyPaint)
> g.fill(bodyOutline)
> 
> #Draw Face
> g.draw(bodyShape)
> g.setPaint(event.source.background)
> g.fill(bodyShape)
> g.setPaint(Color.DARK_GRAY)
> g.draw(bodyShape)
> 
> #Set Font
> g.setFont(event.source.font)
> 
> #Tick Marks
> theta = -math.pi/2
> for tick in xrange(60):
> 	
> tickLength = event.source.MinorTickLength if tick % 5 else event.source.MajorTickLength
> #calculate the start and end points for the tick line
> x1 = radius * math.cos(theta) + cX
> y1 = radius * math.sin(theta) + cY
> x2 = (radius - tickLength) * math.cos(theta) + cX
> y2 = (radius - tickLength) * math.sin(theta) + cY
> 	
> 	
> tickLine = Line2D.Float(x1,y1,x2,y2)
> if tick % 5:
> g.setColor(event.source.MinorTickColor)
> g.setStroke(BasicStroke(event.source.MinorTickWidth))
> else:
> g.setColor(event.source.MajorTickColor)
> g.setStroke(BasicStroke(event.source.MajorTickWidth))
> 		
> g.draw(tickLine)
> 	
> #Draw the tick increment text
> if not tick % 5:
> 		
> 		
> fontMetrics = g.getFontMetrics()
> x2 = (radius - tickLength - (fontMetrics.getHeight() /2.0 + fontMetrics.getAscent()/5)) * math.cos(theta) + cX - (fontMetrics.stringWidth(str(tick)) / 2.0)
> y2 = (radius - tickLength - (fontMetrics.getHeight() /2.0 + fontMetrics.getAscent()/5)) * math.sin(theta) + cY + 4
> g.setColor(event.source.foreground)
> #Uncomment if you would rather it say 60 than 0
> #if tick == 0:
> #	g.drawString("60",x2,y2)
> #else:
> #tab in the next line if you uncomment the above code.
> g.drawString(str(tick),x2,y2)
> 		
> #increment theta to next angle
> theta += math.radians(360/60)
> 
> #Draw the Set-Point hand
> g.setPaint(Color.ORANGE)
> 
> spNeedle = Path2D.Float()
> radPerTick = math.radians(360/60)
> value = event.source.Setpoint
> 
> spNeedle.moveTo((radius-45) * math.cos(value * radPerTick - math.pi / 2) + cX,(radius-45) * math.sin(value * radPerTick - math.pi / 2) + cY)
> spNeedle.lineTo(3 * math.cos(value * radPerTick - math.pi) + cX,3 *math.sin(value * radPerTick - math.pi) + cY)
> spNeedle.curveTo(15 * math.cos(value * radPerTick - 5 * math.pi/4) + cX, 15 * math.sin(value * radPerTick - 5 * math.pi/4) + cY,15 * math.cos(value * radPerTick + math.pi/4) + cX,15 * math.sin(value * radPerTick + math.pi/4) + cY, 3 * math.cos(value * radPerTick) + cX, 3 * math.sin(value * radPerTick) + cY)
> spNeedle.closePath()
> g.fill(spNeedle)
> 
> #Draw the Value-Hand
> value = event.source.Value
> g.setPaint(Color.BLACK)
> vNeedle = Path2D.Float()
> vNeedle.moveTo(radius * math.cos(value * radPerTick - math.pi/2) + cX, radius * math.sin(value * radPerTick - math.pi/2) + cY)
> vNeedle.lineTo(3 * math.cos(value * radPerTick - math.pi) + cX, 3 * math.sin(value * radPerTick - math.pi) + cY)
> vNeedle.curveTo(15 * math.cos(value * radPerTick - 5 * math.pi/4) + cX, 15 * math.sin(value * radPerTick - 5 * math.pi/4) + cY, 15 * math.cos(value * radPerTick + math.pi/4) + cX, 15 * math.sin(value * radPerTick + math.pi/4) + cY, 3 * math.cos(value * radPerTick) + cX, 3 * math.sin(value * radPerTick) + cY)
> vNeedle.closePath()
> g.fill(vNeedle)
> 
> g.setPaint(event.source.SetpointColor)
> 
> #Draw Set Point Text
> fm = g.getFontMetrics()
> g.drawString(str(event.source.Setpoint),cX - fm.stringWidth(str(event.source.Setpoint)) / 2.0, cY + 50 )
> 
> #Draw Value Text
> g.setPaint(event.source.ValueColor)
> g.drawString(str(event.source.Value),cX - fm.stringWidth(str(event.source.Value)) / 2.0, cY + 65 )
> 
> ```

![stopwatch](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/1/f1d4cc17222bbc29ce5c09d32d4c317beebbc1cc.gif)

---

<div class="post-metadata">

**Author:** ![jay](https://avatars.discourse-cdn.com/v4/letter/j/ed8c4c/32.png) [@jay](https://forum.inductiveautomation.com/u/jay)\
**Post date:** [May 5, 2023, 10:14pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/27 "2023-05-05T22:14:32Z")

</div>

I use rotating Vision objects frequently. I never have a problem like this when I use a style customizer to drive the rotation. You'd have 60 rows in your rotation table for this situation, but that should be OK.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [May 6, 2023, 12:52am UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/28 "2023-05-06T00:52:43Z")

</div>

If you only care about integer values, sure that will work, but if you want any higher precision (which @steven.rehnborg seems to from the OP) and it balloons to unworkable. Just a single decimal place and you’re already at 600 entries.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [May 6, 2023, 10:38am UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/29 "2023-05-06T10:38:59Z")

</div>

> [@lrose](#):
>
> Just a single decimal place and you’re already at 600 entries.

I remember looking into something like this before while working on [a different problem](https://forum.inductiveautomation.com/t/automatic-function/66619/24). I believe that 60 lines would work even with decimals if the goal is to rotate the hand in one second increments. Nevertheless, the paintable canvas approach is the one I would implement for this usage case.

---

<div class="post-metadata">

**Author:** ![steven.rehnborg](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/steven.rehnborg/32/4952_2.png) [@steven.rehnborg](https://forum.inductiveautomation.com/u/steven.rehnborg)\
**Post date:** [May 8, 2023, 11:15am UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/30 "2023-05-08T11:15:02Z")

</div>

Actually, I don't need anything more precise than seconds. The main concern is minutes in process for the cycle, but fractions (seconds) are recorded. Didn't mean to imply I needed more accuracy.

I will try this out. I'm not familiar with the paintable canvas yet, so I'll be doing some study. Thanks all for the help! I think my issue has technically been resolved even if my question still remains for what happens to the objects in dynamic rotation.

---

<div class="post-metadata">

**Author:** ![steven.rehnborg](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/steven.rehnborg/32/4952_2.png) [@steven.rehnborg](https://forum.inductiveautomation.com/u/steven.rehnborg)\
**Post date:** [May 8, 2023, 2:48pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/31 "2023-05-08T14:48:59Z")

</div>

have you had any trouble with re-sizing?

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [May 8, 2023, 3:09pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/32 "2023-05-08T15:09:00Z")

</div>

No, I didn't have any unforeseen issues with re-sizing. The code doesn't account for changes in aspect ratio, so as long as the height and width are close to the same ratio, you should get decent results. If you get too far off you'll start to see some weird things, like the tick marks not being centered exactly. This is because they are drawn assuming a perfect circle. That can be fixed, I just didn't take the time to do it.

There are also some things which I hard coded based on the original size that I used (such as the position of the labels). The code doesn't account for repositioning those based on the height and width of the template. That is easily done though.

If for instance you change line 114 and 118 to something like this:

```auto
#line 114
g.drawString(str(event.source.Setpoint),cX-fm.stringWidth(str(event.source.Setpoint)) / 2.0, cY + event.height / 8)

#line 118
g.drawString(str(event.source.Value),cX - fm.stringWidth(str(event.source.Value)) / 2.0, cY + event.height / 6)

```

The position of the labels will stay relatively the same.

---

<div class="post-metadata">

**Author:** ![steven.rehnborg](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/steven.rehnborg/32/4952_2.png) [@steven.rehnborg](https://forum.inductiveautomation.com/u/steven.rehnborg)\
**Post date:** [May 8, 2023, 3:39pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/33 "2023-05-08T15:39:14Z")

</div>

I was trying to hold aspect ratio, but when I actually checked, it was off a small amount. Changing it manually fixed the issue with the tickmarks. Your code fixed the value location, thanks!  
I have one more issue, but I'm going to dig into the code to fix it myself. Gives me a reason to become more familiar with the coding of this.  
Thanks!

Comparison shot:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/6/46b2cbd8b4417d4ce296744a692a788c53d21986.png)

---

<div class="post-metadata">

**Author:** ![steven.rehnborg](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/steven.rehnborg/32/4952_2.png) [@steven.rehnborg](https://forum.inductiveautomation.com/u/steven.rehnborg)\
**Post date:** [May 16, 2023, 2:43pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/34 "2023-05-16T14:43:41Z")

</div>

Something new with the paintable canvas for the timer. Getting this error below when page is opened. Once the Error box is closed, the alarm does not come back unless the page is opened again. Related to the clock setpoint hand because the error is on the line that draws the setpoint hand. An almost identical line for the process variable hand does not error.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/2/5/2558b20f3659d0781d1d73a7f0d9f2eb55cb5d4a.png)

spNeedle.moveTo((radius-20) \* math.cos(value \* radPerTick - math.pi / 2) + cX,(radius-20) \* math.sin(value \* radPerTick - math.pi / 2) + cY)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 16, 2023, 3:07pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/35 "2023-05-16T15:07:21Z")

</div>

The component is paintable before its bindings have finished, and value is still null. You have to handle that case in your repaint event.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [May 16, 2023, 4:05pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/36 "2023-05-16T16:05:47Z")

</div>

> [@pturmel](#):
>
> You have to handle that

An interesting question would be how to handle it. Obviously, wrapping the whole thing in a quick and dirty try, except, pass would get rid of the exception, but that would also get rid of any other exception that could happen for whatever reason down the road. Wouldn't some sort of initial binding verification be better? ...and if so, what is the best practice for accomplishing this?

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [May 16, 2023, 4:06pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/37 "2023-05-16T16:06:45Z")

</div>

Just change the value assignment lines to something like this and it will eliviate your issue.

```auto
value = event.source.Setpoint if event.source.Setpoint else 0

```

You might see a slight flash of the needle being drawn at 0 before the binding completes.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [May 16, 2023, 4:09pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/38 "2023-05-16T16:09:53Z")

</div>

> [@lrose](#):
>
> `value = event.source.Setpoint if event.source.Setpoint else 0`

This makes sense. A null value will evaluate as false and set the hand to the zero [starting] position.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 16, 2023, 4:24pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/39 "2023-05-16T16:24:34Z")

</div>

I would test it at the beginning and not paint at all if null.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [May 16, 2023, 4:35pm UTC](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822/40 "2023-05-16T16:35:05Z")

</div>

> [@pturmel](#):
>
> test it at the beginning

```auto
if event.source.Setpoint:
     #entire repaint script

```

[Previous page](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822.md?page=1)

[Next page](https://forum.inductiveautomation.com/t/rotating-graphic-is-changing-sizes-at-random/71822.md?page=3)
