Adding vertical lines when clicking on graph

Functions with callbacks inside are tricky, because if you call the functions multiple times it tries to add another callback. Which causes the callback error that you are encountering.

To avoid this, you need to bring the dash callbacks out of the function. I don’t know how you’d accomplish this with the setup that you have, it’s rather interesting.

Just tried to work with your code, unfortunately, the libraries didnt import, so I couldnt run it.

No problem I solved it. I just added a global counter and change the debugID each call:

import sys
from plotly.graph_objects import Figure, Scatter, FigureWidget
import threading
from PySide2 import QtCore
from PyQt5 import QtWidgets
from plotly import *
import dash
import dash_core_components as dcc
import dash_html_components as html
import sys
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import QApplication
import numpy as np
import json
from dash.dependencies import Input, Output, State


clicked=[]
countDebug=0
def getLenClicks():
    return len(clicked)

def run_dash(data, layout):
    app = dash.Dash()

    app.layout = html.Div(children=[
        dcc.Graph(
            id='fig',
            figure={
                'data': data,
                'layout': layout
            }),dash.html.Div(id="debug"),
        ])
    
    @app.callback(
        Output("debug", "children"),
        Input("fig", "clickData"),
    )
    def point_clicked(clickData):
        global clicked
        lenClicks=getLenClicks()
        if lenClicks==2:
            clicked=[]
        points=clickData.get('points')
        x=points[0].get('x')
        clicked.append(x)
        print(clicked)
        
        
        
    app.run_server(debug=False)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):

        super(MainWindow, self).__init__()
        web = QWebEngineView()
        
        data = [
        {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'scatter', 'name': 'SF'},
        {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'scatter', 'name': u'Montréal'},
        ]

        layout = {
        'title': 'Dash Data Visualization'
        }
        fig=FigureWidget(data,layout)
        self.qdask = QDash()
        self.qdask.run(debug=True, use_reloader=False)
        self.qdask.update_graph(fig)
        web.load(QUrl("http://127.0.0.1:8050"))
        self.setCentralWidget(web)
        data = [
        {'x': [3,5,6], 'y': [4, 1, 2], 'type': 'scatter', 'name': 'SF'},
        {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'scatter', 'name': u'Montréal'},
        ]

        layout = {
        'title': 'Dash Data Visualization'
        }
        fig1=FigureWidget(data,layout)
        self.qdask.update_graph(fig1)
        web.reload()
        
        
        #web.load(QUrl("https://www.google.com"))
        
        
class QDash(QtCore.QObject):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._app = dash.Dash()
        self._app.layout = html.Div()

    def update_graph(self, df):
        global countDebug
        countDebug+=1
        debugId="debug"+str(countDebug)
        fig = df
        self._app.layout = html.Div(children=[
                dcc.Graph(
                    id='fig',
                    figure={
                        'data': fig.data,
                        'layout': fig.layout
                    }),dash.html.Div(id=debugId),
                ])
        @self._app.callback(
            [Output(debugId, "children")],
            Input("fig", "clickData")
        )
        def point_clicked(clickData):
            global clicked
            if len(clicked)==2:
                clicked=[]
            points=clickData.get('points')
            x=points[0].get('x')
            clicked.append(x)
            print(clicked)
    
    def run(self, **kwargs):
        threading.Thread(target=self._app.run_server, kwargs=kwargs, daemon=True).start()       
   

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec_())
1 Like