Paintable Canvas not refreshing completely

I'm having trouble getting a Paintable Canvas to work perfectly.
I've got a template with a Paintable Canvas that's drawing a polygon to represent the shape of a part, based on information stored in a dataset tag. Everything works, except that when I update the dataset tag, the Paintable Canvas doesn't refresh as I'd like it to. It'll partially draw the new shape, but the old one is still there. It seems like it needs to be cleared or refreshed in some way. I have a Numeric Entry field on the template as well, and if I click in there the Paintable Canvas updates like it should. But obviously I want it to repaint and refresh or whatever it has to do, without having to click somewhere else.

Here are screenshots to show what's happening. The first image shows what it looks like after I've clicked the "Flip" button (which swaps data points in the dataset tag to flip the part vertically):

And here's what the Paintable Canvas should be showing:

Here's my code:

from java.awt import Color
from java.awt.geom import Path2D

# Generate the polygon points
sorted_point_list = generatePartPoints.calculate(
					event.source.parent.Saw1_EN, event.source.parent.Saw2_EN, event.source.parent.Saw3_EN, event.source.parent.Saw4_EN, event.source.parent.Saw5_EN,
					event.source.parent.Saw1_Angle, event.source.parent.Saw2_Angle, event.source.parent.Saw3_Angle, event.source.parent.Saw4_Angle, event.source.parent.Saw5_Angle,
					event.source.parent.Saw1_CL, event.source.parent.Saw2_CL, event.source.parent.Saw3_CL, event.source.parent.Saw4_CL, event.source.parent.Saw5_CL,
					event.height-2, event.width-2

# Initialize max variables
max_y = float('-inf')
max_x = float('-inf')

# Iterate through the points to find the maximum X & Y coordinates
for point in sorted_point_list:
    max_y = max(max_y, point[1])
    max_x = max(max_x, point[0])

# Flip the points so that 0,0 is in the top left corner
sorted_point_list = [[point[0], max_y - point[1]] for point in sorted_point_list]

# Create a Path2D object to represent the polygon
polygon_path = Path2D.Double()
polygon_path.moveTo(sorted_point_list[0][0], sorted_point_list[0][1])

# Iterate through the points and add them to the path
for point in sorted_point_list[1:]:
    polygon_path.lineTo(point[0], point[1])

# Close the polygon

# Create a graphics object
graphics =

# Set the color for the polygon outline
outline_color = Color(0, 0, 0)

# Draw the polygon

# Dispose of the graphics object to free up resources

Mm, not sure this is your issue, but you should not do this.

OK, I took that out. The result is the same.

Where are you handling the dataset? I don't see it in the code. (A paintable canvas redraws when one of its own properties changes--it doesn't pay any attention to its container's properties. Make sure you aren't racing.)

I have a custom property on the Paintable Canvas called "trigger", which is bound to a client memory tag called "trussDisplayUpdateTrigger". When I click the button to flip or rotate the part, it calls a function from the Project Library that updates the relevant row in the dataset, and then it sets the update tag with the milliseconds of the current time, which should trigger a repaint.

The template properties referenced by the Paintable Canvas code are connected with the dataset. On one window I have a template repeater showing the template containing the canvas, using the dataset as its Template Parameters. On another window I have only one instance of the template showing, with its properties all bound to the dataset with an expression like this: {[edge]CutLists/fileDataSet}[{MainAutoControl.PartVisual.Index},"Saw1_Angle"]

The behaviour of the Paintable canvas is similar on both windows. On the window with the Template Repeater, the canvas looks like the first picture above until I move the mouse off of the Flip or Rotate button. On the window with a single instance of the template, I have to click into the Numeric Entry field or toggle the visibility of the template to get it to refresh.

OK, I think I got it. I added more custom properties to the Paintable Canvas itself, bound to the template properties, which are in turn bound to the dataset. Now it refreshes immediately like I wanted it to. For some reason it was not sufficient to just have the trigger property.

I suspect your trigger property was updated before the container properties. (That's what I meant by "racing".) Is there any reason you don't bind the dataset directly to a property of the canvas?

Ok, that makes sense.

I guess there isn't. I've never used a Template Repeater before, so I'd set that up first, and made Template Properties to match the dataset column names, and then I'd just pulled from those template properties for the script on the Paintable Canvas. But there's no reason that I couldn't just have all my properties right on the Paintable Canvas and have them bound indirectly to the dataset. I just hadn't thought of it.