plotly / dash-canvas

An interactive image editing component for Dash
https://dash.plot.ly/canvas
Other
84 stars 26 forks source link

Switching between Dash application tabs clears the annotations on a canvas #31

Open nikandrovs94 opened 4 years ago

nikandrovs94 commented 4 years ago

I have created two Dash tabs for my application and each tab has a canvas with a background image. When I annotate one canvas by drawing, for example, rectangles, and then switch to the other tab and back to the initial one, the rectangles disappear but the background image remains in the canvas. How should I go about this issue?

emmanuelle commented 4 years ago

Hey @nikandrovs94 (sorry for the slow response), could you please share here a minimal example reproducing the issue?

nikandrovs94 commented 4 years ago

Thanks for your reply, @emmanuelle ! Please find the minimal code below. I use it to select an image for dash canvas background via file browser (you can pick any image you have to test it).

Just to clarify: The issue is that when I draw on the canvas in the first tab and then switch to the second tab and back to the first one, any lines that I drew are erased. It seems like the canvas is getting refreshed or something. Is there any way for the canvas to maintain users drawings while switching between dash tabs?

Thanks, Mike

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash_canvas import DashCanvas
from dash_canvas.utils import (array_to_data_url, parse_jsonstring, parse_jsonstring_line,
                               parse_jsonstring_rectangle, image_string_to_PILImage)

import sys, os, webbrowser, win32ui, win32con
from skimage import io
from PIL import Image
import numpy as np

def gui_select_file(start_dir=None):
    '''
    Opens a browser and returns the path to the selected file.
    '''
    fd = win32ui.CreateFileDialog(1)

    fd.SetOFNTitle('Select contour file')

    if fd.DoModal()==win32con.IDCANCEL:
        sys.exit(1)

    filepath = fd.GetPathName()

    return filepath

filename = gui_select_file()

#Read the image file
image = Image.open(filename)
image_array = np.asarray(image)

shape = io.imread(filename, as_gray=True).shape
img_width = shape[1]
img_height = shape[0]

#Manually set the canvas dimensions
canvas_width = 800
canvas_scale = canvas_width/img_width
canvas_height = round(img_height*canvas_scale)

app = dash.Dash(__name__)
tabs_styles = {
    'height': '50px',
    'font-size': '22px',
    'fontWeight': 'bold',
}
tab_style = {
    'borderBottom': '2px solid #d6d6d6',
    'padding': '6px',
    'vertical-align': 'middle',
    'align-items': 'center',
    'justify-content': 'center',
}

tab_selected_style = {
    'borderTop': '1px solid #d6d6d6',
    'borderBottom': '1px solid #d6d6d6',
    'backgroundColor': '#119DFF',
    'color': 'white',
    'padding': '6px'
}

app.config.suppress_callback_exceptions = True

app.layout = html.Div(
    children=[

        dcc.Tabs(
            id='tabs',
            style=tabs_styles,
            children=[

                #Calibration tab
                dcc.Tab(
                    label='Calibration',
                    style=tab_style,
                    selected_style=tab_selected_style,
                    children=[

                        #Generate Dash canvas
                        DashCanvas(
                             lineWidth=2,
                             hide_buttons=['line', 'pencil'],
                             image_content=array_to_data_url(image_array),
                             lineColor='red',
                             width=canvas_width,
                             goButtonTitle='Extract Information'
                        )
                    ]
                ),

                #Calibration tab
                dcc.Tab(
                    label='Measurements',
                    style=tab_style,
                    selected_style=tab_selected_style,
                    children=[

                        #Generate Dash canvas
                        DashCanvas(
                             lineWidth=2,
                             hide_buttons=['line', 'pencil'],
                             image_content=array_to_data_url(image_array),
                             lineColor='red',
                             width=canvas_width,
                             goButtonTitle='Extract Information'
                        )
                    ]
                )
            ]
        )
    ]
)

my_port = 8050

if __name__ == '__main__':
    url = "http://127.0.0.1:{}/".format(my_port)
    webbrowser.open_new_tab(url)

    app.server.run(port=my_port, host='127.0.0.1')