0

I'm using CircuitPython to draw text and shapes on an LCD, which works. I detect interaction (a rotary encoder) and want to change a shape's colour, when I detect a certain state. This also works but I have created a function to remove the shape and the text overlaying it then place another shape (same size & position but different colour) and then replace the original text back over that. I'm getting the following error

Traceback (most recent call last):
  File "<stdin>", line 249, in <module>
  File "<stdin>", line 206, in toggleCircle
ValueError: object not in sequence

The relevant parts of my code:

...
# Make the displayio SPI bus and the GC9A01 display
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=tft_rst)
display = gc9a01.GC9A01(display_bus, width=240, height=240, backlight_pin=tft_bl)
...
# Make the main display context
main = displayio.Group()
display.show(main)
circle = Circle(-25,120,circleRad, fill=  0x555555 )
modeCircle = Circle(-25,120,circleRad, fill=  0x0045D0 )
...
#Draw central hub text
tmp = "18.5°C"
hum = "53%"
delta = "4:19"
tim = "13:34"

TempTxt = label.Label(terminalio.FONT, text=tmp, color=0xFFFFFF, anchor_point=(0.5,0.5), anchored_position=(0,0))
HumTxt = label.Label(terminalio.FONT, text=hum, color=0xFFFFFF, anchor_point=(0.5,0.5), anchored_position=(0,-12))
DeltaTxt = label.Label(terminalio.FONT, text=delta, color=0xFFFFFF, anchor_point=(0.5,0.5), anchored_position=(0,12))
TimeTxt = label.Label(terminalio.FONT, text=tim, color=0xFFFFFF, anchor_point=(0.5,0.5), anchored_position=(0,24))

StatusGrp = displayio.Group(scale=2)
StatusGrp.append(TempTxt)
StatusGrp.append(HumTxt) 
StatusGrp.append(DeltaTxt)
StatusGrp.append(TimeTxt)
StatusGrp.x = 50
StatusGrp.y = 108

main.append(HumGrp)
main.append(TimerGrp)
main.append(MaxGrp)
main.append(OffGrp)
main.append(circle)
main.append(StatusGrp)
...
mode = 0 #position and therefore mode seems to be a bit lossy, so use x & y coordinate check to determine mode
ActiveModeX = int(sweepRad * math.cos(0))-re
ActiveModeY = int(sweepRad * math.sin(0))+120

# cater for rounding errors or other minor inaccuracies with a comparison with a tolerance margin
def near(a,b,within):
    if ((a >= b-within) and (a <= b+within)):
        return True
    else:
        return False
    
def toggleCircle(sel):
    if sel == 1:
        main.remove(circle)
        main.remove(StatusGrp)
        main.append(modeCircle) #remove grey circle and replace it with coloured circle ie mode selected
        main.append(StatusGrp)
    elif sel == 0:
        main.remove(modeCircle)
        main.remove(StatusGrp)
        main.append(circle) #remove grey circle and replace it with coloured circle ie mode selected
        main.append(StatusGrp)

while True:
    position = encoder.position
    if last_position is None or position != last_position:
        theta = position * math.pi/virtualDetents
        
        HumGrp.x = int(sweepRad * math.cos(theta))-re
        HumGrp.y = int(sweepRad * math.sin(theta))+120
        TimerGrp.x = int(sweepRad * math.cos((theta-math.pi/2))-re) #-(math.pi/2)
        TimerGrp.y = int(sweepRad * math.sin((theta-math.pi/2))+120)
        MaxGrp.x = int(sweepRad * math.cos((theta-math.pi))-re) #-(math.pi/2)
        MaxGrp.y = int(sweepRad * math.sin((theta-math.pi))+120)
        OffGrp.x = int(sweepRad * math.cos((theta+math.pi/2))-re) #-(math.pi/2)
        OffGrp.y = int(sweepRad * math.sin((theta+math.pi/2))+121)
        time.sleep(0.2)
        
        #use x & y coordinate check to determine mode - much more reliable than using rotary encoder, which can get out of sync
        if (near(HumGrp.x,ActiveModeX,1) and near(HumGrp.y,ActiveModeY,1) and mode != "humidity"):
            print("Mode: Humidity")
            mode = "humidity"
            toggleCircle(1)
        elif (near(TimerGrp.x,ActiveModeX,1) and near(TimerGrp.y,ActiveModeY,1) and mode != "timer"):
            print("Mode: Timer")
            mode = "timer"
            toggleCircle(1)
        elif (near(MaxGrp.x,ActiveModeX,1) and near(MaxGrp.y,ActiveModeY,1) and mode != "max"):
            print("Mode: Max")
            mode = "max"
            toggleCircle(1)
        elif (near(OffGrp.x,ActiveModeX,1) and near(OffGrp.y,ActiveModeY,1) and mode != "off"):
            print("Mode: Off")
            mode = "off"
            toggleCircle(1)
#         else:
#             print("Mode: Not a mode")
#             toggleCircle(0)

Despite the error message, I'm not sure what I'm looking for. Please help

Greg
  • 195
  • 1
  • 13
  • Supplementary question:. Is remove and replace the correct way of achieving this or can I somehow reference the circle and change its colour attribute? – Greg Jun 14 '23 at 13:17

1 Answers1

-1

If you run the togglecircle() function twice in a row with both 1s or both 0s, then it will already have removed the circle or modecircle from the last time. To fix, try using a try:, except: block around the removing parts of the code

try:
    main.remove(circle)
    main.remove(StatusGrp)
except:
    pass
main.append(modeCircle)
main.append(StatusGrp)

Hopefully this fixes your problem.