Боке добавить стрелку динамически - PullRequest
0 голосов
/ 13 апреля 2020

Я новичок в использовании Bokeh. Для моего проекта я пытаюсь использовать боке, чтобы сделать стрелки из одной точки в другую. Поэтому я делаю точки, дважды щелкнув, а затем рисуя стрелки одним щелчком мыши. Но, похоже, это ничего не делает.

from bokeh.models import Arrow, OpenHead
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
from bokeh.io import curdoc
from bokeh.events import DoubleTap, Tap

coordList=[]
source = ColumnDataSource(data=dict(x=[], y=[]))

#add a dot where the click happened
def callback(event):
    Coords=(event.x,event.y)
    coordList.append(Coords)
    source.data = dict(x=[i[0] for i in coordList], y=[i[1] for i in coordList])
    for x, y in coordList:
        if x == None and y ==  None:
            coordList.pop(0)
p = figure(plot_width=700, plot_height=700)

def draw(event):
    # Function to add arrows from the coordList
    p.add_layout(Arrow(end=OpenHead(line_color="firebrick", line_width=4),
                   x_start=1, y_start=1, x_end=4, y_end=4))

p.circle(source=source,x='x',y='y')
p.on_event(DoubleTap, callback)
p.on_event(Tap, draw)

curdoc().add_root(p)

Любая помощь будет принята с благодарностью. Спасибо

1 Ответ

1 голос
/ 14 апреля 2020

Да, это ошибка: https://github.com/bokeh/bokeh/issues/8862

Смотрите мои комментарии в строке.

from bokeh.events import DoubleTap, Tap
from bokeh.io import curdoc
from bokeh.models import Arrow, OpenHead, CustomJS
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure

p = figure(plot_width=700, plot_height=700)
# We need to have at least one renderer present for the plot
# to be able to compute the initial ranges. Otherwise, the very
# first double tap event will have no coordinates.
bogus_renderer = p.circle(x=[0], y=[0], fill_alpha=0, line_alpha=0)

# This is needed to make sure that PlotView recalculates
# all renderers' views when we call `add_layout`.
p.js_on_change('center', CustomJS(code='cb_obj.properties.renderers.change.emit();'))

source = ColumnDataSource(data=dict(x=[], y=[]))


def callback(event):
    # Removing the renderer to avoid messing with DataRange1d.
    bogus_renderer.data_source.data = dict(x=[], y=[])
    source.stream(dict(x=[event.x], y=[event.y]))


def draw(event):
    if source.data['x']:
        last_dot_x = source.data['x'][-1]
        lalt_dot_y = source.data['y'][-1]
        p.add_layout(Arrow(end=OpenHead(line_color="firebrick", line_width=4),
                           x_start=last_dot_x, y_start=lalt_dot_y, x_end=event.x, y_end=event.y))


p.circle(source=source, x='x', y='y')
p.on_event(DoubleTap, callback)
p.on_event(Tap, draw)

curdoc().add_root(p)
...