<p><code>broken_barh</code>不创建单个条,而是创建一个大的<code>BrokenBarHCollection</code>对象。
当调用<code>contains(event)</code>时,返回<code>False</code>或<code>True</code>,同时返回索引,指示单击了哪个小条</p>
<p>用<code>.get_paths()[ind].get_extents()</code>可以得到那个小条的边界框。边界框的坐标表示开始时间和持续时间</p>
<pre class="lang-py prettyprint-override"><code>import matplotlib.pyplot as plt
fig, ax_gnt = plt.subplots()
ax_gnt.set_ylim(0, 50)
ax_gnt.set_xlim(0, 65)
ax_gnt.set_yticks([10, 25])
ax_gnt.set_yticklabels(['Algo_1', 'Algo_2'])
ax_gnt.grid(True)
# For Algo-1 Solution
ax_gnt.broken_barh([(5, 9), (14, 1), (15, 4), (19, 9), (28, 4), (34, 4), (38, 5)], (5, 10),
facecolors={'tab:blue', 'tab:red', 'tab:olive', 'tab:pink', 'tab:cyan', 'tab:brown', 'tab:orange'})
# For Algo-2 Solution
ax_gnt.broken_barh([(14, 6), (22, 4), (29, 7), (36, 3), (39, 15)], (20, 10),
facecolors={'tab:blue', 'tab:red', 'tab:olive', 'tab:pink', 'tab:cyan'})
annot = ax_gnt.annotate("", xy=(0, 0), xytext=(20, 30), textcoords="offset points",
bbox=dict(boxstyle="round", fc="yellow", ec="b", lw=2),
arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)
def update_annot(brokenbar_collection, coll_id, ind, x, y):
annot.xy = (x, y)
box = brokenbar_collection.get_paths()[ind].get_extents()
text = f"{ax_gnt.get_yticklabels()[coll_id].get_text()} index:{ind} duration:{box.x1 - box.x0:.0f} "
annot.set_text(text)
annot.get_bbox_patch().set_alpha(0.9)
def hover(event):
vis = annot.get_visible()
if event.inaxes == ax_gnt:
for coll_id, brokenbar_collection in enumerate(ax_gnt.collections):
cont, ind = brokenbar_collection.contains(event)
if cont:
update_annot(brokenbar_collection, coll_id, ind['ind'][0], event.xdata, event.ydata)
annot.set_visible(True)
fig.canvas.draw_idle()
return
if vis:
annot.set_visible(False)
fig.canvas.draw_idle()
fig.canvas.mpl_connect("motion_notify_event", hover)
plt.show()
</code></pre>
<p><a href="https://i.stack.imgur.com/JhF8E.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/JhF8E.png" alt="example plot"/></a></p>