Home > Net >  Position Elements of Plotly-Dash App Layout
Position Elements of Plotly-Dash App Layout

Time:11-30

I'm creating a dash app where I can upload an image and perform image processing on it. I've gone through the Dash tutorials but there is little to no info on how to position the various elements on the page.

For example, I want my uploaded image to show up on the right and below the title and "Drag and Drop..." button and other sliders and checkboxes to show up on the left. I've attached a sample image below.

Below is what I have so far:

style = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=style)


colors = {
    'title': '#FFFFFF',
    'text': '#AOAABA',
    'background': '#161A1D'
}

app.layout = html.Div([
    html.H2("Object Detection and Image Processing",
                style={'textAlign':'center',
                        'color': colors['text']}),
    html.Hr(),
    html.H3("Upload Image Below To Get Started",
                style={'textAlign':'center',
                       'color': colors['text']}),
    dcc.Upload(
        id='upload-image',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        },
        # Allow multiple files to be uploaded
        multiple=True
        ),
    html.Div(id='output-image-upload'),
])

def parse_contents(contents, filename, date):
    return html.Div([
        html.H5(filename),
        html.H6(datetime.datetime.fromtimestamp(date)),

        # HTML images accept base64 encoded strings in the same format as upload
        html.Img(src=contents)
    ])

@app.callback(Output('output-image-upload', 'children'),
              Input('upload-image', 'contents'),
              State('upload-image', 'filename'),
              State('upload-image', 'last_modified'))

def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
        return children

if __name__ == '__main__':
    app.run_server(debug=True)

Below is what I wish it to look like:

enter image description here

CodePudding user response:

You could wrap the contents of the two columns in two separate html.Div() with the following style:

style = {
    'display': 'inline-block',
    'vertical-align': 'top'
}

This will ensure that the two columns are stacked horizontally and aligned at the top.

import datetime
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State

style = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=style)

colors = {
    'title': '#FFFFFF',
    'text': '#AOAABA',
    'background': '#161A1D'
}

app.layout = html.Div([

    # Header.
    html.H2(
        children='Object Detection and Image Processing',
        style={'textAlign': 'center', 'color': colors['text']}
    ),

    html.Hr(),

    # First column.
    html.Div(
        
        children=[
            
            html.H3(
                children='Upload Image Below To Get Started',
                style={'textAlign': 'center', 'color': colors['text']}
            ),

            dcc.Upload(
                id='upload-image',
                children=html.Div([
                    'Drag and Drop or ',
                    html.A('Select Files')
                ]),
                style={
                    'width': '100%',
                    'height': '60px',
                    'lineHeight': '60px',
                    'borderWidth': '1px',
                    'borderStyle': 'dashed',
                    'borderRadius': '5px',
                    'textAlign': 'center',
                    'margin': '10px'
                },
                multiple=True
            ),
            
        ],
        
        style={
            'display': 'inline-block',
            'vertical-align': 'top'
        }
        
    ),

    # Second column.
    html.Div(

        children=[
            html.Div(id='output-image-upload'),
        ],

        style={
            'display': 'inline-block',
            'vertical-align': 'top',
            'margin-left': '100px'
        }
        
    )

])

def parse_contents(contents, filename, date):

    return html.Div([
        html.H5(filename),
        html.H6(datetime.datetime.fromtimestamp(date)),
        html.Img(src=contents)
    ])

@app.callback(Output('output-image-upload', 'children'),
              Input('upload-image', 'contents'),
              State('upload-image', 'filename'),
              State('upload-image', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)
        ]
        return children

if __name__ == '__main__':
    app.run_server(debug=True, host='127.0.0.1')
  • Related