pythonnicegui

NiceGUI Interactive Image - Does changing source periodically refreshes/resets the content as well


I am using an interactive image to show live stream video (code from NiceGUI openCV example) I am able to successfully show the live feed using the ui.timer. However, I also do some operations with my mouse over the image like recording mouse clicks. The interactive image holds the content if it's a static image. But for a video, since the image (source) refreshes due to change of path every 0.1 sec, the content refreshes as well. Maybe the element refreshes all together when set_source is called?

How can we only change/refresh the set_source while still preserving the content property.

class SVGContent:
   def __init__(self):
      self.content = ''

svgContent = SVGContent()

def mouse_handler(e: MouseEventArguments):
   if e.type == 'click':
      svgContent.content += f'<circle cx="{e.image_x}" cy="{e.image_y}" r="15" fill="none" stroke="{color}" stroke-width="4" />'


ii = ui.interactive_image(
   on_mouse = mouse_handler, 
   events=['click', 'mousedown', 'mouseup'], 
   cross=True
)
ui.timer(interval=0.1, callback=lambda: ii.set_source(f'http://localhost:3000/video/stream1?{time.time()}'))
        
ii.bind_content_from(svgContent, 'content')


Solution

  • Actually I fixed it myself.

    I didn't provide an online URL while declaring the interactive image and then with the timer I was setting the source. This was resulting in the clicks (along with SVG) not rendering coz the images were reloading.

    However, providing the source at the declaration itself, and removing the timer solved the issue.

    class SVGContent:
       def __init__(self):
          self.content = ''
    
    svgContent = SVGContent()
    
    def mouse_handler(e: MouseEventArguments):
       if e.type == 'click':
          svgContent.content += f'<circle cx="{e.image_x}" cy="{e.image_y}" r="15" fill="none" stroke="{color}" stroke-width="4" />'
    
    
    ii = ui.interactive_image(
       source = 'http://localhost:3000/video/stream1')) 
       on_mouse = mouse_handler, 
       events=['click', 'mousedown', 'mouseup'], 
       cross=True
    )
    # ui.timer(interval=0.1, callback=lambda: ii.set_source(f'http://localhost:3000/video/stream1?{time.time()}'))
            
    ii.bind_content_from(svgContent, 'content')
    

    Please note: The API returns a StreamResponse and hence no need to add query to path. Only if your API is a normal Response, then you might have to use timer and add path query as well to ignore browser cache.