基于悬停数据高亮表格行的Dash可视化开发需求
实现Dash图像悬停时表格行高亮功能
需求背景
已搭建Dash可视化界面:通过下拉框选择数字标签,可展示对应样本图像及包含标签、样本索引的表格。需新增交互能力:鼠标悬停在图像上时,表格中对应样本的行自动高亮。
实现方案
- 新增
dcc.Store组件存储当前悬停的样本索引,作为图像与表格之间的状态中转桥梁 - 扩展回调逻辑,监听图像的
hoverData事件,提取悬停位置对应的样本索引 - 通过表格的
style_data_conditional属性,根据存储的索引配置高亮样式 - 切换下拉标签时自动重置高亮状态,避免残留旧状态
修改后的完整代码
from dash import Dash, dcc, html, Input, Output, callback, State from dash import dash_table import plotly.express as px import pandas as pd import numpy as np # 生成合成数据 samples = [200,10,5,40,60,100,2,100,9,10] idx = [n for n in range(10)] for i,smp in zip(idx,samples): if i == 0: X = np.full((smp,96, 96), i/10) y = np.full((smp,),i) else: tempx = np.full((smp,96, 96), i/10) tempy = np.full((smp,),i) X = np.r_[X,tempx] y = np.r_[y,tempy] app = Dash(__name__) tbl_cols = ['Choice','Samples'] app.layout = html.Div([ # 存储当前悬停的样本索引 dcc.Store(id='hovered_sample', data=None), dcc.Dropdown([i for i in range(10)], 0, id='my_dropdown'), html.Div([ html.Div([ dcc.Graph(id='my_picbox',style={'display':'inline-block'}) ],style={'width': '40%', 'display': 'inline-block'}), html.Div([ dash_table.DataTable( id = 'table', columns = [{'name': i, 'id': i} for i in tbl_cols], # 默认基础样式 style_data={ 'whiteSpace': 'normal', 'height': 'auto', } ), ],style={'width': '60%', 'display': 'inline-block'}) ],style={'display': 'flex'}) ]) @callback( [Output(component_id='my_picbox', component_property='figure'), Output(component_id='table', component_property='data'), Output(component_id='hovered_sample', component_property='data')], Input(component_id='my_dropdown', component_property='value'), prevent_initial_call=False ) def update_plot(digit): if digit is not None: samples = np.where(y==digit)[0] if len(samples)>20: samples = np.random.choice(samples,20) imgs = np.empty((20,96,96),) imgs[:]= np.nan imgs[0:len(samples)]=X[samples, :, :] fig = px.imshow(imgs[:, :, :], binary_string=False, zmin=0, zmax=1, facet_col=0, aspect = 'auto', facet_col_wrap=5, facet_row_spacing = 0, color_continuous_scale='rdylgn') for i in fig.layout.annotations: n = int(i['text'].split('=')[1]) try: i['text']=str(samples[n]) except: i['text']=' ' fig.update_layout(margin = dict(t=70, l=50, r=0, b=5), height = 600, width = 600,) df = pd.DataFrame(data = {'Samples':samples}) df['Choice'] = digit data = df[tbl_cols].to_dict('records') # 切换下拉选项时重置悬停状态 return fig, data, None @callback( Output(component_id='table', component_property='style_data_conditional'), Input(component_id='my_picbox', component_property='hoverData'), State(component_id='table', component_property='data'), State(component_id='hovered_sample', component_property='data'), prevent_initial_call=False ) def highlight_table_row(hover_data, table_data, current_hover): # 初始化样式列表 styles = [] if hover_data is not None: # 提取悬停图像对应的分栏位置 facet_num = hover_data['points'][0]['facet_col'] # 匹配表格中对应行的样本索引 if facet_num < len(table_data): hovered_sample = table_data[facet_num]['Samples'] # 添加高亮样式规则 styles.append({ 'if': {'filter_query': f'Samples = {hovered_sample}'}, 'backgroundColor': '#ffff99', 'fontWeight': 'bold' }) return styles if __name__ == '__main__': app.run_server(debug=True, port=8056)
核心逻辑说明
- 状态管理:
dcc.Store组件用于在下拉切换标签时重置悬停状态,避免旧高亮残留 - 悬停数据解析:通过
hoverData中的facet_col字段获取当前悬停图像的位置,对应表格中的行索引 - 表格高亮配置:利用
style_data_conditional属性,通过样本索引匹配目标行,设置高亮背景色与字体权重
内容的提问来源于stack exchange,提问作者Arindam
相关产品推荐
相关产品推荐

