实现鼠标交互
1. 实现鼠标点击节点高亮
直接上代码:
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
fig, ax = plt.subplots(figsize=(10,10))
node_pos = [(1, 0), (0, 1), (2,1), (1,2)]
bbox_args = dict(boxstyle="round", fc="0.8")
arrow_args = dict(arrowstyle="->")
an1 = plt.annotate(s="Test 1\n(node1,node2)\n(node3,node4,node5)\n\n\n", xy=node_pos[0], xycoords="data",
va="center", ha="center",
bbox=dict(boxstyle="round", fc="w", facecolor='green'))
an2 = plt.annotate(s="Test 2\n(node1,node2)", xy=node_pos[1], xycoords="data",
va="center", ha="center",
bbox=dict(boxstyle="round", fc="w", facecolor='green'))
arrow1 = plt.annotate('', xy=(0, 0), xycoords=an1,
xytext=(0, 0), textcoords=an2, # an1 -> an2
size=20, ha="center", va="center",
bbox=bbox_args,
arrowprops=dict(patchA=an2,
patchB=an1,
connectionstyle="arc3,rad=0.2",
#color='red',
#linewidth=5,
**arrow_args))
arrow2 = plt.annotate('', xy=(0, 0), xycoords=an2,
xytext=(0, 0), textcoords=an1, # an1 -> an2
size=20, ha="center", va="center",
bbox=bbox_args,
arrowprops=dict(patchA=an1,
patchB=an2,
connectionstyle="arc3,rad=0.2",
#color='red',
#linewidth=5,
**arrow_args))
# callback fun
def mouse_click(event):
if an1.contains(event)[0] == True: # 获取鼠标事件
an1.set_bbox(dict(facecolor='red', alpha= 0.5, boxstyle= 'round'))
fig.canvas.draw() # 切记要加上这句,否则,回调函数中的参数无法更新
axes = plt.gca()
axes.set_xlim([-2,2])
axes.set_ylim([-2,2])
fig.canvas.mpl_connect('button_press_event', mouse_click)
主要就是实现回调函数onclick
。通过点击test1
,实现背景高亮。
注意
切记要加上fig.canvas.draw()
,否则回调函数中的参数无法更新。这个bug找了好久,都是泪。
2. 实现鼠标悬停在节点,显示节点信息。
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
fig, ax = plt.subplots(figsize=(10,10))
node_pos = [(1, 0), (0, 1), (2,1), (1,2)]
bbox_args = dict(boxstyle="round", fc="0.8")
arrow_args = dict(arrowstyle="->")
an1 = plt.annotate(s="Test 1\n(node1,node2)\n(node3,node4,node5)\n\n\n", xy=node_pos[0], xycoords="data",
va="center", ha="center",
bbox=bbox_args)
an2 = plt.annotate(s="Test 2\n(node1,node2)", xy=node_pos[1], xycoords="data",
va="center", ha="center",
bbox=bbox_args)
arrow1 = plt.annotate('', xy=(0, 0), xycoords=an1,
xytext=(0, 0), textcoords=an2, # an1 -> an2
size=20, ha="center", va="center",
bbox=bbox_args,
arrowprops=dict(patchA=an2,
patchB=an1,
connectionstyle="arc3,rad=0.2",
#color='red',
#linewidth=5,
**arrow_args))
arrow2 = plt.annotate('', xy=(0, 0), xycoords=an2,
xytext=(0, 0), textcoords=an1, # an1 -> an2
size=20, ha="center", va="center",
bbox=bbox_args,
arrowprops=dict(patchA=an1,
patchB=an2,
connectionstyle="arc3,rad=0.2",
#color='red',
#linewidth=5,
**arrow_args))
#fig.canvas.draw()
node_pos = an1.get_position()
tag1 = plt.annotate(s='hello node1', xy=node_pos, xycoords='data',
color='red',
xytext=(node_pos[0] + 0.3, node_pos[1] + 0.3),
textcoords='data', horizontalalignment="left",
bbox=bbox_args,
annotation_clip=True
)
tag1.set_visible(False)
# callback fun
def mouse_click(event):
if an1.contains(event)[0] == True: # 获取鼠标事件
if an1.get_color() != 'red':
an1.set_color('red') # set font color
an1.set_bbox(dict(facecolor='yellow', alpha=1, boxstyle='round'))
else:
an1.set_color('black') # set font color
an1.set_bbox(bbox_args)
fig.canvas.draw() # 切记要加上这句,否则,回调函数中的参数无法更新
# check mouse enter
def mouse_enter(event):
visible_change_flag = False
visible_flag = an1.contains(event)[0] #注意,这里检查节点an1是否包含鼠标,而不是tag1
if visible_flag != tag1.get_visible():
visible_change_flag = True
tag1.set_visible(visible_flag)
if visible_change_flag:
fig.canvas.draw()
axes = plt.gca()
axes.set_xlim([-2,2])
axes.set_ylim([-2,2])
fig.canvas.mpl_connect('button_press_event', mouse_click)
fig.canvas.mpl_connect('motion_notify_event', mouse_enter)
效果图
注意
- 这里检查节点an1是否包含鼠标,而不是tag1
- 鼠标悬停事件是
motion_notify_event
,而不是button_press_event