Bokeh HoverTool仅显示单个tooltip问题求助
Got it, let's fix that multiple tooltip issue you're seeing with Bokeh's HoverTool! The problem here is that you've added three separate vbar glyphs to your plot, and the HoverTool is triggering on each one individually—even with mode='vline', it's picking up every glyph that intersects the vertical line and showing a tooltip for each.
Here are two straightforward ways to get that single-tooltip behavior you want:
Option 1: Explicitly tell HoverTool which glyph to target
You can assign your vbar glyphs to variables, then set the renderers parameter on the HoverTool to only one of them. Since all your glyphs use the same ColumnDataSource, the tooltip will still pull all the relevant data (IN, OUT, STOCK, DT) from the source, but only show once.
Modify your code like this:
from bokeh.models import (HoverTool, ColumnDataSource, Title, DatetimeTickFormatter) import pandas as pd from bokeh.io import show, output_file from bokeh.plotting import figure def assembly_chart(df, complements): """function to assembly the chart""" output_file("movigrama_chart.html") source = ColumnDataSource(df) p = figure(x_axis_type='datetime', x_axis_label='days of moviment', y_axis_label='unities movimented', plot_width=1230, plot_height=500, active_scroll='wheel_zoom') # Assign each vbar to a variable stock_bar = p.vbar(x='DT', bottom=0, top='STOCK', width=pd.Timedelta(days=1), fill_alpha=0.4, color='#99d8c9', source=source) out_bar = p.vbar(x='DT', bottom=0, top='SOMA_SAI', width=pd.Timedelta(days=1), fill_alpha=0.8, color='crimson', source=source) in_bar = p.vbar(x='DT', bottom=0, top='SOMA_ENTRA', width=pd.Timedelta(days=1), fill_alpha=0.8, color='seagreen', source=source) # Keep all your existing plot styling code here p.add_layout(Title(text=complements['warehouse'], text_font='helvetica', text_font_size='10pt', text_color='orangered', text_alpha=0.5, align='center', text_font_style="italic"), 'above') p.add_layout(Title(text=complements['product'], text_font='helvetica', text_font_size='10pt', text_color='orangered', text_alpha=0.5, align='center', text_font_style="italic"), 'above') p.add_layout(Title(text='Movigrama Endicon', text_font='helvetica', text_font_size='16pt', text_color='orangered', text_alpha=0.9, align='center', text_font_style="bold"), 'above') p.x_range.range_padding = 0.1 p.y_range.range_padding = 0.1 p.outline_line_width = 4 p.outline_line_alpha = 0.1 p.outline_line_color = 'orangered' p.axis.major_label_text_color = 'gray' p.axis.major_label_text_font_style = 'bold' p.axis.axis_label_text_color = 'gray' p.axis.axis_label_text_font_style = 'bold' p.axis.major_tick_out = 10 p.axis.minor_tick_in = -3 p.axis.minor_tick_out = 6 p.axis.minor_tick_line_color = 'gray' p.xaxis.formatter = DatetimeTickFormatter( days=['%d/%m'], months=['%m/%Y'], years=['%Y']) # Configure HoverTool to target only one glyph hover = HoverTool() hover.mode = 'vline' # activate hover by vertical line hover.tooltips = [("IN", "@SOMA_ENTRA"), ("OUT", "@SOMA_SAI"), ("STOCK", "@STOCK"), ("DT", "@DT{%d/%m/%Y}")] hover.formatters = {"DT": 'datetime'} # Only target one glyph (any will work since they share the same data source) hover.renderers = [stock_bar] p.add_tools(hover) show(p)
Option 2: Add a hidden dummy glyph to trigger the tooltip
If you don't want to tie the tooltip to a specific visible bar, you can add an invisible glyph (like a circle with size 0) that covers the x-range, and set the HoverTool to only trigger on that. This ensures the tooltip shows exactly once per vertical line, regardless of the visible bars:
from bokeh.models import (HoverTool, ColumnDataSource, Title, DatetimeTickFormatter) import pandas as pd from bokeh.io import show, output_file from bokeh.plotting import figure def assembly_chart(df, complements): """function to assembly the chart""" output_file("movigrama_chart.html") source = ColumnDataSource(df) p = figure(x_axis_type='datetime', x_axis_label='days of moviment', y_axis_label='unities movimented', plot_width=1230, plot_height=500, active_scroll='wheel_zoom') # Add invisible dummy glyph to trigger tooltip dummy = p.circle(x='DT', y=0, size=0, source=source) # Your existing vbar code p.vbar(x='DT', bottom=0, top='STOCK', width=pd.Timedelta(days=1), fill_alpha=0.4, color='#99d8c9', source=source) p.vbar(x='DT', bottom=0, top='SOMA_SAI', width=pd.Timedelta(days=1), fill_alpha=0.8, color='crimson', source=source) p.vbar(x='DT', bottom=0, top='SOMA_ENTRA', width=pd.Timedelta(days=1), fill_alpha=0.8, color='seagreen', source=source) # Keep all your existing plot styling code here p.add_layout(Title(text=complements['warehouse'], text_font='helvetica', text_font_size='10pt', text_color='orangered', text_alpha=0.5, align='center', text_font_style="italic"), 'above') p.add_layout(Title(text=complements['product'], text_font='helvetica', text_font_size='10pt', text_color='orangered', text_alpha=0.5, align='center', text_font_style="italic"), 'above') p.add_layout(Title(text='Movigrama Endicon', text_font='helvetica', text_font_size='16pt', text_color='orangered', text_alpha=0.9, align='center', text_font_style="bold"), 'above') p.x_range.range_padding = 0.1 p.y_range.range_padding = 0.1 p.outline_line_width = 4 p.outline_line_alpha = 0.1 p.outline_line_color = 'orangered' p.axis.major_label_text_color = 'gray' p.axis.major_label_text_font_style = 'bold' p.axis.axis_label_text_color = 'gray' p.axis.axis_label_text_font_style = 'bold' p.axis.major_tick_out = 10 p.axis.minor_tick_in = -3 p.axis.minor_tick_out = 6 p.axis.minor_tick_line_color = 'gray' p.xaxis.formatter = DatetimeTickFormatter( days=['%d/%m'], months=['%m/%Y'], years=['%Y']) # Configure HoverTool to use the dummy glyph hover = HoverTool() hover.mode = 'vline' hover.tooltips = [("IN", "@SOMA_ENTRA"), ("OUT", "@SOMA_SAI"), ("STOCK", "@STOCK"), ("DT", "@DT{%d/%m/%Y}")] hover.formatters = {"DT": 'datetime'} hover.renderers = [dummy] p.add_tools(hover) show(p)
Why this works:
By default, HoverTool listens to all renderers in the plot. When you set renderers to a single glyph, it only triggers that one tooltip—since all your glyphs share the same ColumnDataSource, the tooltip still pulls all the data points for the current x-value (DT) from the source, giving you all the info you need in one place.
Either approach will give you that clean single-tooltip look you're aiming for with the vertical line mode.
内容的提问来源于stack exchange,提问作者Arnold Souza

